HyperionIManager.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include <hyperion/HyperionIManager.h>
  2. // hyperion
  3. #include <hyperion/Hyperion.h>
  4. #include <db/InstanceTable.h>
  5. // qt
  6. #include <QThread>
  7. HyperionIManager* HyperionIManager::HIMinstance;
  8. HyperionIManager::HyperionIManager(const QString& rootPath, QObject* parent, bool readonlyMode)
  9. : QObject(parent)
  10. , _log(Logger::getInstance("HYPERION-INSTMGR"))
  11. , _instanceTable( new InstanceTable(rootPath, this, readonlyMode) )
  12. , _rootPath( rootPath )
  13. , _readonlyMode(readonlyMode)
  14. {
  15. HIMinstance = this;
  16. qRegisterMetaType<InstanceState>("InstanceState");
  17. }
  18. Hyperion* HyperionIManager::getHyperionInstance(quint8 instance)
  19. {
  20. Hyperion* pInstance {nullptr};
  21. if(_runningInstances.contains(instance))
  22. return _runningInstances.value(instance);
  23. if (!_runningInstances.isEmpty())
  24. {
  25. Warning(_log,"The requested instance index '%d' with name '%s' isn't running, return main instance", instance, QSTRING_CSTR(_instanceTable->getNamebyIndex(instance)));
  26. pInstance = _runningInstances.value(0);
  27. }
  28. return pInstance;
  29. }
  30. QVector<QVariantMap> HyperionIManager::getInstanceData() const
  31. {
  32. QVector<QVariantMap> instances = _instanceTable->getAllInstances();
  33. for( auto & entry : instances)
  34. {
  35. // add running state
  36. entry["running"] = _runningInstances.contains(entry["instance"].toInt());
  37. }
  38. return instances;
  39. }
  40. void HyperionIManager::startAll()
  41. {
  42. for(const auto & entry : _instanceTable->getAllInstances(true))
  43. {
  44. startInstance(entry["instance"].toInt());
  45. }
  46. }
  47. void HyperionIManager::stopAll()
  48. {
  49. // copy the instances due to loop corruption, even with .erase() return next iter
  50. QMap<quint8, Hyperion*> instCopy = _runningInstances;
  51. for(const auto instance : instCopy)
  52. {
  53. instance->stop();
  54. }
  55. }
  56. void HyperionIManager::suspend()
  57. {
  58. Info(_log,"Suspend all instances and enabled components");
  59. QMap<quint8, Hyperion*> instCopy = _runningInstances;
  60. for(const auto instance : instCopy)
  61. {
  62. emit instance->suspendRequest(true);
  63. }
  64. }
  65. void HyperionIManager::resume()
  66. {
  67. Info(_log,"Resume all instances and enabled components");
  68. QMap<quint8, Hyperion*> instCopy = _runningInstances;
  69. for(const auto instance : instCopy)
  70. {
  71. emit instance->suspendRequest(false);
  72. }
  73. }
  74. void HyperionIManager::toggleIdle(bool isIdle)
  75. {
  76. Info(_log,"Put all instances in %s state", isIdle ? "idle" : "working");
  77. QMap<quint8, Hyperion*> instCopy = _runningInstances;
  78. for(const auto instance : instCopy)
  79. {
  80. emit instance->idleRequest(isIdle);
  81. }
  82. }
  83. void HyperionIManager::toggleStateAllInstances(bool enable)
  84. {
  85. // copy the instances due to loop corruption, even with .erase() return next iter
  86. QMap<quint8, Hyperion*> instCopy = _runningInstances;
  87. for(const auto instance : instCopy)
  88. {
  89. emit instance->compStateChangeRequest(hyperion::COMP_ALL, enable);
  90. }
  91. }
  92. bool HyperionIManager::startInstance(quint8 inst, bool block, QObject* caller, int tan)
  93. {
  94. if(_instanceTable->instanceExist(inst))
  95. {
  96. if(!_runningInstances.contains(inst) && !_startQueue.contains(inst))
  97. {
  98. QThread* hyperionThread = new QThread();
  99. hyperionThread->setObjectName("HyperionThread");
  100. Hyperion* hyperion = new Hyperion(inst, _readonlyMode);
  101. hyperion->moveToThread(hyperionThread);
  102. // setup thread management
  103. connect(hyperionThread, &QThread::started, hyperion, &Hyperion::start);
  104. connect(hyperion, &Hyperion::started, this, &HyperionIManager::handleStarted);
  105. connect(hyperion, &Hyperion::finished, this, &HyperionIManager::handleFinished);
  106. connect(hyperion, &Hyperion::finished, hyperionThread, &QThread::quit, Qt::DirectConnection);
  107. // setup further connections
  108. // from Hyperion
  109. connect(hyperion, &Hyperion::settingsChanged, this, &HyperionIManager::settingsChanged);
  110. connect(hyperion, &Hyperion::videoMode, this, &HyperionIManager::requestVideoMode);
  111. // to Hyperion
  112. connect(this, &HyperionIManager::newVideoMode, hyperion, &Hyperion::newVideoMode);
  113. // add to queue and start
  114. _startQueue << inst;
  115. hyperionThread->start();
  116. // update db
  117. _instanceTable->setLastUse(inst);
  118. _instanceTable->setEnable(inst, true);
  119. if(block)
  120. {
  121. while(!hyperionThread->isRunning()){};
  122. }
  123. if (!_pendingRequests.contains(inst) && caller != nullptr)
  124. {
  125. PendingRequests newDef{caller, tan};
  126. _pendingRequests[inst] = newDef;
  127. }
  128. return true;
  129. }
  130. Debug(_log,"Can't start Hyperion instance index '%d' with name '%s' it's already running or queued for start", inst, QSTRING_CSTR(_instanceTable->getNamebyIndex(inst)));
  131. return false;
  132. }
  133. Debug(_log,"Can't start Hyperion instance index '%d' it doesn't exist in DB", inst);
  134. return false;
  135. }
  136. bool HyperionIManager::stopInstance(quint8 inst)
  137. {
  138. // inst 0 can't be stopped
  139. if(!isInstAllowed(inst))
  140. return false;
  141. if(_instanceTable->instanceExist(inst))
  142. {
  143. if(_runningInstances.contains(inst))
  144. {
  145. // notify a ON_STOP rather sooner than later, queued signal listener should have some time to drop the pointer before it's deleted
  146. emit instanceStateChanged(InstanceState::H_ON_STOP, inst);
  147. Hyperion* hyperion = _runningInstances.value(inst);
  148. hyperion->stop();
  149. // update db
  150. _instanceTable->setEnable(inst, false);
  151. return true;
  152. }
  153. Debug(_log,"Can't stop Hyperion instance index '%d' with name '%s' it's not running'", inst, QSTRING_CSTR(_instanceTable->getNamebyIndex(inst)));
  154. return false;
  155. }
  156. Debug(_log,"Can't stop Hyperion instance index '%d' it doesn't exist in DB", inst);
  157. return false;
  158. }
  159. bool HyperionIManager::createInstance(const QString& name, bool start)
  160. {
  161. quint8 inst;
  162. if(_instanceTable->createInstance(name, inst))
  163. {
  164. Info(_log,"New Hyperion instance created with name '%s'",QSTRING_CSTR(name));
  165. emit instanceStateChanged(InstanceState::H_CREATED, inst, name);
  166. emit change();
  167. if(start)
  168. startInstance(inst);
  169. return true;
  170. }
  171. return false;
  172. }
  173. bool HyperionIManager::deleteInstance(quint8 inst)
  174. {
  175. // inst 0 can't be deleted
  176. if(!isInstAllowed(inst))
  177. return false;
  178. // stop it if required as blocking and wait
  179. stopInstance(inst);
  180. if(_instanceTable->deleteInstance(inst))
  181. {
  182. Info(_log,"Hyperion instance with index '%d' has been deleted", inst);
  183. emit instanceStateChanged(InstanceState::H_DELETED, inst);
  184. emit change();
  185. return true;
  186. }
  187. return false;
  188. }
  189. bool HyperionIManager::saveName(quint8 inst, const QString& name)
  190. {
  191. if(_instanceTable->saveName(inst, name))
  192. {
  193. emit change();
  194. return true;
  195. }
  196. return false;
  197. }
  198. void HyperionIManager::handleFinished()
  199. {
  200. Hyperion* hyperion = qobject_cast<Hyperion*>(sender());
  201. quint8 instance = hyperion->getInstanceIndex();
  202. Info(_log,"Hyperion instance '%s' has been stopped", QSTRING_CSTR(_instanceTable->getNamebyIndex(instance)));
  203. _runningInstances.remove(instance);
  204. hyperion->thread()->deleteLater();
  205. hyperion->deleteLater();
  206. emit instanceStateChanged(InstanceState::H_STOPPED, instance);
  207. emit change();
  208. }
  209. void HyperionIManager::handleStarted()
  210. {
  211. Hyperion* hyperion = qobject_cast<Hyperion*>(sender());
  212. quint8 instance = hyperion->getInstanceIndex();
  213. Info(_log,"Hyperion instance '%s' has been started", QSTRING_CSTR(_instanceTable->getNamebyIndex(instance)));
  214. _startQueue.removeAll(instance);
  215. _runningInstances.insert(instance, hyperion);
  216. emit instanceStateChanged(InstanceState::H_STARTED, instance);
  217. emit change();
  218. if (_pendingRequests.contains(instance))
  219. {
  220. PendingRequests def = _pendingRequests.take(instance);
  221. emit startInstanceResponse(def.caller, def.tan);
  222. _pendingRequests.remove(instance);
  223. }
  224. }