Main Page · Modules · All Classes · Class Hierarchy
MSContext.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MSContext.hpp"
23 
24 #include <signal.h>
25 
26 #ifdef AP_CPU_PROFILER
27 #include <gperftools/profiler.h>
28 #endif
29 
30 #include <qapplication.h>
31 #include <qdir.h>
32 #include <qfont.h>
33 #include <QMap>
34 #include <QTime>
35 
36 #include <MCDefs.hpp>
37 #include <MCLog.hpp>
38 
39 #include "MSDefs.hpp"
40 #include "MSElement.hpp"
41 #include "MSHeart.hpp"
42 #include "MSSessionStorage.hpp"
43 
44 typedef struct
45 {
46  QTime Timer;
47  QString Description;
48  int Time;
49 } TimerData;
50 
51 // Singleton instance
52 static MSContext* Singleton = nullptr;
53 // Singleton instance of the session storage
54 static MSSessionStorage* SessionStorageSingleton = nullptr;
55 // Singleton instance of the heart beat
56 static MSHeart* HeartSingleton = nullptr;
57 // QCoreApplication/QApplication instance
58 static QCoreApplication* App = nullptr;
59 // Hash of timers
60 static QMap<QString, TimerData> Timers;
61 // Pause timer
62 static QTime* PauseTimer = nullptr;
63 // Malfunction status
64 static bool MalfunctionStatus = false;
65 
66 extern "C" {
67 static void MSSignalHandler(int signal_id)
68 {
69  bool LastHeartBeat = false;
70 
71  MC_BPRINT(MCLog::White, "\nSignal caught: ");
72  switch (signal_id)
73  {
74  case SIGFPE:
75  MC_BPRINT(MCLog::White, "Floating point exception...D'oh!\n\n");
76 #if defined(__unix__) && !defined(__ANDROID__)
77  MCGenerateBacktrace();
78 #endif
79  break;
80  case SIGSEGV:
81  MC_BPRINT(MCLog::White, "Segmentation fault...D'oh!\n\n");
82 #if defined(__unix__) && !defined(__ANDROID__)
83  MCGenerateBacktrace();
84 #endif
85  break;
86  case SIGILL:
87  MC_BPRINT(MCLog::White, "Illegal instruction...D'oh!\n\n");
88 #if defined(__unix__) && !defined(__ANDROID__)
89  MCGenerateBacktrace();
90 #endif
91  break;
92  case SIGINT:
93  MC_BPRINT(MCLog::White, "Ctrl+C pressed?!...D'oh!\n\n");
94 #if defined(__unix__) && !defined(__ANDROID__)
95  MCGenerateBacktrace();
96 #endif
97  LastHeartBeat = true;
98  break;
99  case SIGTERM:
100  MC_BPRINT(MCLog::White, "Kill signal received...D'oh!\n\n");
101 #if defined(__unix__) && !defined(__ANDROID__)
102  MCGenerateBacktrace();
103 #endif
104  LastHeartBeat = true;
105  break;
106 #if defined(__MINGW32__) || defined(__MINGW64__)
107  case SIGBREAK:
108  MC_BPRINT(MCLog::White, "Ctrl+Break pressed...D'oh!\n\n");
109  LastHeartBeat = true;
110  break;
111 #endif
112  case SIGABRT:
113  MC_BPRINT(MCLog::White, "Abnormal termination...D'oh!\n\n");
114 #if defined(__unix__) && !defined(__ANDROID__)
115  MCGenerateBacktrace();
116 #endif
117  break;
118  default:
119  MC_BPRINT(MCLog::White, "Unsupported signal?...D'oh!\n\n");
120  break;
121  }
122 
123  // Deinstall the signal handlers
124  signal(SIGFPE, SIG_DFL);
125  signal(SIGSEGV, SIG_DFL);
126  signal(SIGILL, SIG_DFL);
127  signal(SIGINT, SIG_DFL);
128  signal(SIGTERM, SIG_DFL);
129 #if defined(__MINGW32__) || defined(__MINGW64__)
130  signal(SIGBREAK, SIG_DFL);
131 #endif
132  signal(SIGABRT, SIG_DFL);
133 
134  MalfunctionStatus = true;
135  // Request the last heart beat
136  if (LastHeartBeat && HeartSingleton && HeartSingleton->IsBeatingActive())
137  {
138  MC_NPRINT("Request to stop the heart beating...\n");
139  HeartSingleton->StopBeating();
140  return;
141  }
142 
143  // Close the recorded session
144  if (SessionStorageSingleton && !SessionStorageSingleton->GetRecordPath().isEmpty())
145  {
146  MC_NPRINT("Try to close the streams in the recorded sessions...\n");
147  SessionStorageSingleton->Finalize();
148  }
149 
150  // Exit if we do not have to wait for the heart beating
151  if (!HeartSingleton || !HeartSingleton->IsBeatingActive())
152  {
153  exit(1);
154  }
155 }
156 }
157 
158 QStringList MSContext::CmdArgumentMsgs = QStringList() <<
159  "ca_ArgumentNotFound" <<
160  "ca_ArgumentFound" <<
161  "ca_ArgumentFoundWithParameter";
162 
163 MSContext::MSContext(int& argc, char** argv, bool graphical_context) : CPUProfiling(false),
164  DefaultDebugItems(""), SessionPrepared(false), SessionRuntimeTimerName("SessionRuntime")
165 {
166  if (Singleton)
167  {
168  MC_ERROR("Only one MSContext instance can be created!");
169  }
170  // Set a new number as random seed
172  qsrand(QDateTime::currentDateTimeUtc().toTime_t());
173  srand(QDateTime::currentDateTimeUtc().toTime_t());
174 
175  if (graphical_context)
176  {
177  QApplication* QtContext = new QApplication(argc, argv);
178  // Set the font to something standard and readable
179  boost::scoped_ptr<QFont> AppFont(new QFont("Courier New", 10));
180 
181  QtContext->setFont(*AppFont);
182  App = QtContext;
183  } else {
184  App = new QCoreApplication(argc, argv);
185  }
186 #if defined(__MINGW32__) || defined(__MINGW64__)
187  // Add the current path to search Qt plug-ins (e.g sqlite backend)
188  App->addLibraryPath(QDir::currentPath());
189  App->addLibraryPath(QString(AIBOPLUS_SOURCE_ROOT)+MC_DIR_SEPARATOR+"libs"+MC_DIR_SEPARATOR+"Qt"+
190  MC_DIR_SEPARATOR+"plugins");
191 #endif
192  // Singleton pattern
193  Singleton = this;
194  // Heartbeat singleton
195  HeartSingleton = new MSHeart();
196  connect(HeartSingleton, SIGNAL(BeatBegin(int)), this, SIGNAL(NewHeartBeat(int)), Qt::QueuedConnection);
197  connect(HeartSingleton, SIGNAL(Finished()), this, SLOT(HeartFinished()), Qt::QueuedConnection);
198  connect(this, SIGNAL(Stop()), HeartSingleton, SLOT(StopBeating()), Qt::QueuedConnection);
199 
200  // Session storage singleton
201  SessionStorageSingleton = MSSessionStorage::GetInstance();
202  SessionStorageSingleton->connect(SessionStorageSingleton, SIGNAL(EndOfDatabase()),
203  this, SIGNAL(PlayedSessionFinished()));
204  SessionStorageSingleton->connect(HeartSingleton, SIGNAL(StorageForCurrentBeat(int)),
205  SessionStorageSingleton, SLOT(BeatEnd(int)));
206 
207  // Store the program arguments
208  ProgramArguments = App->arguments();
210  // Clear vector of registered elements
211  RegElements.clear();
212  // Install signal handlers
213  signal(SIGFPE, MSSignalHandler);
214  signal(SIGSEGV, MSSignalHandler);
215  signal(SIGILL, MSSignalHandler);
216  signal(SIGINT, MSSignalHandler);
217  signal(SIGTERM, MSSignalHandler);
218 #if defined(__MINGW32__) || defined(__MINGW64__)
219  signal(SIGBREAK, MSSignalHandler);
220 #endif
221  signal(SIGABRT, MSSignalHandler);
222  // Register the run time timer
223  RegisterTimer(SessionRuntimeTimerName, "Session runtime");
224 }
225 
226 
228 {
229  // Clear vector of registered elements
230  RegElements.clear();
231  Singleton = nullptr;
232 
233  // Disconnect Stop signal
234  disconnect();
235  // Delete session storage singleton
236  if (SessionStorageSingleton)
237  {
238  SessionStorageSingleton->disconnect();
239  delete SessionStorageSingleton;
240  SessionStorageSingleton = nullptr;
241  }
242  // Delete heart singleton
243  if (HeartSingleton)
244  {
245  HeartSingleton->disconnect();
246  delete HeartSingleton;
247  HeartSingleton = nullptr;
248  }
249  // Stop the CPU profiler
250  if (CPUProfiling)
251  {
252 #ifdef AP_CPU_PROFILER
253  ProfilerStop();
254 #endif
255  CPUProfiling = false;
256  }
257  // Clear timer hash
258  Timers.clear();
259  // Destroy the application instance
260  if (App)
261  {
262  delete App;
263  App = nullptr;
264  }
265 }
266 
267 
269 {
270  if (!Singleton)
271  {
272  MC_ERROR("MSContext instance can not be created by MSContext::GetInstance()");
273  }
274  return Singleton;
275 }
276 
277 
279 {
280  return DefaultDebugItems;
281 }
282 
283 
284 void MSContext::SetDefaultDebugItems(const QString& items)
285 {
286  DefaultDebugItems = items;
287 }
288 
289 
291 {
292  return SessionStorageSingleton->GetPlaybackPath();
293 }
294 
295 
296 void MSContext::SetPlaybackPath(const QString& play_path)
297 {
298  SessionStorageSingleton->SetPlaybackPath(play_path);
299 }
300 
301 
303 {
304  return SessionStorageSingleton->GetRecordPath();
305 }
306 
307 
308 void MSContext::SetRecordPath(const QString& record_path)
309 {
310  if (HeartSingleton->IsBeatingActive())
311  return;
312  SessionStorageSingleton->SetRecordPath(record_path);
313 }
314 
315 
317 {
318  QDateTime CurrentDate = QDateTime::currentDateTime();
319  QString TempStr = MSGetBasePath();
320 
321  TempStr += "/sessions/";
322  TempStr += CurrentDate.toString("yyyy-MM-dd_hh.mm.ss");
323  TempStr += '_'+QString::number(MCRandComplex(0, 1000));
324  return TempStr;
325 }
326 
327 
329 {
330  return HeartSingleton->GetMaxBeats();
331 }
332 
333 
334 void MSContext::SetMaxBeats(int max_beats)
335 {
336  HeartSingleton->SetMaxBeats(max_beats);
337 }
338 
339 
341 {
342  return SessionStorageSingleton->GetPlayedHeartBeats();
343 }
344 
345 
347 {
348  return HeartSingleton->GetCurrentBeat();
349 }
350 
351 
353 {
354  return !RegElements.isEmpty();
355 }
356 
357 
359 {
360  return PauseTimer;
361 }
362 
363 
365 {
366  return HeartSingleton->IsBeatFinished();
367 }
368 
369 
371 {
372  return MalfunctionStatus;
373 }
374 
375 
376 MSContext::ArgSearchResult MSContext::FindArgument(const QString& arg, const QString& long_arg)
377 {
378  int Index = -1;
379  ArgSearchResult Result;
380 
381  Result.Parameter = nullptr;
382  Index = ProgramArguments.indexOf(arg);
383  Index = Index == -1 ? ProgramArguments.indexOf(long_arg) : Index;
384 
385  if (Index == -1)
386  {
387  Result.SearchResult = ca_ArgumentNotFound;
388  return Result;
389  }
390  if (Index > -1 && (Index+1 == ProgramArguments.size() ||
391  ProgramArguments[Index+1].toAscii().data()[0] == '-'))
392  {
393  Result.SearchResult = ca_ArgumentFound;
394  return Result;
395  }
396  Result.SearchResult = ca_ArgumentFoundWithParameter;
397  Result.Parameter = &ProgramArguments[Index+1];
398  return Result;
399 }
400 
401 
402 void MindCoreUsage()
403 {
404  MC_NPRINT("\nCommon options for libmindsession applications:\n"
405  "\n"
406  " -c, --colordebug STRING Colorized debug mode, for the specified\n"
407  " classes/functions.\n"
408  " -d, --debug [STRING] Debug mode, optional argument: Only the specified\n"
409  " classes/functions are debugged, separated by commas.\n"
410 #ifdef AP_CPU_PROFILER
411  " -P, --profiling Run with processor profiler\n"
412 #endif
413  " -b, --beatlimit INT The beat limit for the heart\n"
414  " -h, --help Print this text\n\n");
415 }
416 
417 
419 {
420  ArgSearchResult Result;
421 
422  // Scan for -h or --help argument
423  Result = FindArgument("-h", "--help");
424  if (Result.SearchResult != ca_ArgumentNotFound)
425  {
426  MindCoreUsage();
427  return;
428  }
429  // Scan for -d or --debug argument
430  Result = FindArgument("-d", "--debug");
431  if (Result.SearchResult != ca_ArgumentNotFound)
432  {
433  MCLog::SetDebugStatus(true);
434  if (Result.SearchResult == ca_ArgumentFoundWithParameter)
435  {
436  MCLog::SetDebugFilter(Result.Parameter->toStdString());
437  }
438  }
439  // Scan for -P or --profiling argument
440  Result = FindArgument("-P", "--profiling");
441  if (Result.SearchResult != ca_ArgumentNotFound)
442  {
443  CPUProfiling = true;
444 #ifdef AP_CPU_PROFILER
445  ProfilerStart("./cpu_profiler.perf");
446 #endif
447  }
448  // Scan for -c or --colordebug argument
449  Result = FindArgument("-c", "--colordebug");
450  if (Result.SearchResult == ca_ArgumentFoundWithParameter)
451  {
452  MCLog::SetDebugColorFilters(Result.Parameter->toStdString());
453  }
454 }
455 
456 
458 {
459  MC_BPRINT(MCLog::Blue, "The heart beating has been stopped...\n");
460 
462  {
464 
465  MC_NPRINT("Session run-time: %d ms (heart beats: %d, %.2f ms/beat)\n", RunTime,
466  HeartSingleton->GetCurrentBeat(), (float)RunTime / HeartSingleton->GetCurrentBeat());
467 
468  for (auto iter = Timers.begin(); iter != Timers.end(); ++iter)
469  {
470  if (iter.key() != SessionRuntimeTimerName && iter.value().Time > 0)
471  {
472  MC_NPRINT("%s: %d ms (%.2f %%)\n", iter.value().Description.toAscii().data(),
473  iter.value().Time, (float)iter.value().Time*100 / RunTime);
474  }
475  }
476  }
477  if (SessionPrepared)
478  {
479  FinishSession();
480  }
481  Q_EMIT(HeartStopped());
482 }
483 
484 
486 {
487  SessionStorageSingleton->RegisterStorage(storage);
488 }
489 
490 
492 {
493  MC_LOG("Register element (id: %d) to the context", element.GetElementID());
494  if (element.GetType() != MS::Sink && element.GetType() != MS::SinkGui && SessionPrepared)
495  {
496  MC_WARNING("A session has been prepared. Only sink elements can be registered.");
497  return;
498  }
499  if (element.GetType() != MS::Sink && element.GetType() != MS::SinkGui && HeartSingleton->IsBeatingActive())
500  {
501  MC_WARNING("The heart beating is active. Only sink elements can be registered.");
502  return;
503  }
504  if (RegElements.contains(&element))
505  {
506  MC_WARNING("Element is registered already!");
507  return;
508  }
509  connect(this, SIGNAL(Stop()), &element, SLOT(Stop()));
510  RegElements.append(&element);
511  // Manual registration is needed for sink elements if the heart beating is already active
512  if (HeartSingleton->IsBeatingActive())
513  {
514  HeartSingleton->RequestElementRegistration(element);
515  }
516 }
517 
518 
520 {
521  MC_LOG("Unregister element (id: %d) from the context", element.GetElementID());
522  if (element.GetType() != MS::Sink && element.GetType() != MS::SinkGui && SessionPrepared)
523  {
524  MC_WARNING("A session has been prepared. Only sink elements can be unregistered.");
525  return;
526  }
527  if (element.GetType() != MS::Sink && element.GetType() != MS::SinkGui && HeartSingleton->IsBeatingActive())
528  {
529  MC_WARNING("The heart beating is active. Only sink elements can be unregistered.");
530  return;
531  }
532  if (!RegElements.contains(&element))
533  {
534 // MC_WARNING("Element %s (id: %d) is not registered!", qPrintable(element.GetClass()),
535 // element.GetElementID());
536  return;
537  }
538  if (HeartSingleton->IsElementRegistered(element))
539  {
540  HeartSingleton->UnregisterElement(element);
541  }
542  disconnect(this, SIGNAL(Stop()), &element, SLOT(Stop()));
543  RegElements.removeAt(RegElements.indexOf(&element));
544 }
545 
546 
548 {
549  HeartSingleton->SetBeatDurationLimit(new_limit);
550 }
551 
552 
554 {
555  if (SessionPrepared)
556  {
557  MC_LOG("A session has been prepared already!");
558  return false;
559  }
560  // Prepare to record a session if needed
561  if (!SessionStorageSingleton->GetRecordPath().isEmpty())
562  {
563  SessionStorageSingleton->PrepareRecord();
564  }
565  // Prepare to play a session if needed
566  if (!SessionStorageSingleton->GetPlaybackPath().isEmpty())
567  {
568  SessionStorageSingleton->PreparePlay();
569  }
570  // Register the elements to the storage
571  for (int i = 0; i < RegElements.size(); ++i)
572  {
573  if (RegElements[i]->GetType() == MS::Source &&
574  (!SessionStorageSingleton->GetRecordPath().isEmpty() || !SessionStorageSingleton->GetPlaybackPath().isEmpty()))
575  {
576  SessionStorageSingleton->RegisterElement(*RegElements[i]);
577  }
578  }
579  SessionPrepared = true;
580  return true;
581 }
582 
583 
585 {
586  if (!SessionPrepared)
587  {
588  MC_WARNING("There is no ongoing session to stop!");
589  return;
590  }
591  // Finalize the storage operations
592  SessionStorageSingleton->Finalize();
593  SessionPrepared = false;
594 }
595 
596 
598 {
599  // Start the first heart beat
600  MC_BPRINT(MCLog::Blue, "Start the heart beating...\n");
601  // Prepare the beating if it has not been yet
602  if (!SessionPrepared)
603  {
604  PrepareSession();
605  }
606  // Register the elements to the heart
607  for (int i = 0; i < RegElements.size(); ++i)
608  {
609  HeartSingleton->RegisterElement(*RegElements[i]);
610  }
611  HeartSingleton->StartBeating();
613  // Reset the timers
614  for (auto iter = Timers.begin(); iter != Timers.end(); ++iter)
615  {
616  iter.value().Time = 0;
617  iter.value().Timer.restart();
618  }
619  SessionStorageSingleton->ResetTimers();
620 }
621 
622 
624 {
625  // Stop the heart
626  HeartSingleton->StopBeating();
627 }
628 
629 
631 {
632  HeartSingleton->PauseBeating();
633  PauseTimers();
634 }
635 
636 
638 {
639  HeartSingleton->ResumeBeating();
640  ResumeTimers();
641 }
642 
643 
644 void MSContext::RegisterTimer(const QString& id, const QString& description)
645 {
646  if (id.isEmpty())
647  {
648  MC_WARNING("Empty timer ID.");
649  return;
650  }
651  if (description.isEmpty())
652  {
653  MC_WARNING("Empty timer description.");
654  return;
655  }
656  if (Timers.contains(id))
657  {
658  MC_WARNING("A timer is already registered with the id %s.", id.toAscii().data());
659  return;
660  }
661  TimerData NewTimer;
662 
663  NewTimer.Description = description;
664  NewTimer.Time = 0;
665  Timers[id] = NewTimer;
666 }
667 
668 
669 void MSContext::StartTimer(const QString& id)
670 {
671  if (id.isEmpty())
672  {
673  MC_WARNING("Empty timer ID.");
674  return;
675  }
676  if (!Timers.contains(id))
677  {
678  MC_WARNING("No timer is registered with this id %s.", id.toAscii().data());
679  return;
680  }
681  if (PauseTimer)
682  {
683  MC_WARNING("Timers are paused. Can't start a new timer.");
684  return;
685  }
686  Timers[id].Timer.restart();
687 }
688 
689 
690 void MSContext::StopTimer(const QString& id)
691 {
692  if (id.isEmpty())
693  {
694  MC_WARNING("Empty timer ID.");
695  return;
696  }
697  if (!Timers.contains(id))
698  {
699  MC_WARNING("No timer is registered with this id %s.", id.toAscii().data());
700  return;
701  }
702  if (PauseTimer)
703  {
704  MC_WARNING("Timers are paused. Can't stop a timer.");
705  return;
706  }
707  Timers[id].Time += Timers[id].Timer.elapsed();
708  Timers[id].Timer = QTime();
709 }
710 
711 
712 void MSContext::ResetTimer(const QString& id)
713 {
714  if (id.isEmpty())
715  {
716  MC_WARNING("Empty timer ID.");
717  return;
718  }
719  if (!Timers.contains(id))
720  {
721  MC_WARNING("No timer is registered with this id %s.", id.toAscii().data());
722  return;
723  }
724  if (PauseTimer)
725  {
726  MC_WARNING("Timers are paused. Can't restart a new timer.");
727  return;
728  }
729  Timers[id].Time = 0;
730  Timers[id].Timer = QTime();
731 }
732 
733 
734 int MSContext::GetTimerElapsedTime(const QString& id)
735 {
736  if (id.isEmpty())
737  {
738  MC_WARNING("Empty timer ID.");
739  return 0;
740  }
741  if (!Timers.contains(id))
742  {
743  MC_WARNING("No timer is registered with this id %s.", id.toAscii().data());
744  return 0;
745  }
746  if (PauseTimer)
747  {
748  return Timers[id].Time;
749  }
750  if (Timers[id].Timer.isValid())
751  {
752  Timers[id].Time += Timers[id].Timer.elapsed();
753  Timers[id].Timer = QTime();
754  Timers[id].Timer.start();
755  }
756  return Timers[id].Time;
757 }
758 
759 
761 {
762  if (PauseTimer)
763  {
764  MC_WARNING("Timers are already paused.");
765  return;
766  }
767  PauseTimer = new QTime();
768  PauseTimer->start();
769 }
770 
771 
773 {
774  if (!PauseTimer)
775  {
776  MC_WARNING("Timers have not been paused yet.");
777  return;
778  }
779  int PauseTime = PauseTimer->elapsed();
780 
781  delete PauseTimer;
782  PauseTimer = nullptr;
783  for (auto iter = Timers.begin(); iter != Timers.end(); ++iter)
784  {
785  if (iter.value().Timer.isValid())
786  {
787  iter.value().Time += iter.value().Timer.elapsed()-PauseTime;
788  iter.value().Timer = QTime();
789  iter.value().Timer.start();
790  }
791  }
792 }
int GetPlayedHeartBeats() const
Get the number of the played heart beats.
int GetCurrentBeat() const
Get the current beat ID.
Definition: MSContext.cpp:346
Load or store the source elements&#39; output of a session.
void PreparePlay()
Prepare the play of a recorded session.
static void RegisterTimer(const QString &id, const QString &description)
Register a timer.
Definition: MSContext.cpp:644
QString GenerateRecordPath()
Generate a record path.
Definition: MSContext.cpp:316
void FindMindSessionArgs()
Find libmindsession specific command line arguments.
Definition: MSContext.cpp:418
Creates a context for an application.
Definition: MSContext.hpp:42
void HeartFinished()
Listen to the end of the heart.
Definition: MSContext.cpp:457
Interface class to handle new types in the storage.
static void PauseTimers()
Pause the timers.
Definition: MSContext.cpp:760
int GetElementID() const
Get the element ID.
Definition: MSElement.cpp:83
void ResetTimers()
Reset the internal timers.
bool IsPaused() const
Whenever the context is paused.
Definition: MSContext.cpp:358
void SetRecordPath(const QString &record_path)
Set the path of the record directory.
Definition: MSContext.cpp:308
QString GetDefaultDebugItems() const
Get default active debug items.
Definition: MSContext.cpp:278
void SetPlaybackPath(const QString &path)
Set the playback path.
QString DefaultDebugItems
Default active debugged items.
Definition: MSContext.hpp:555
static MSSessionStorage * GetInstance()
Get a static instance of the class.
Basic ancestor class of the elements.
Definition: MSElement.hpp:65
bool IsMalfunctionHappened() const
Whenever a malfunction happened in the context.
Definition: MSContext.cpp:370
static void ResumeTimers()
Resume the timers.
Definition: MSContext.cpp:772
#define MC_ERROR(...)
Error macro.
Definition: MCLog.hpp:45
static void StartTimer(const QString &id)
Start a timer.
Definition: MSContext.cpp:669
bool SessionPrepared
The heart beating is prepared.
Definition: MSContext.hpp:557
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
virtual void StartHeartBeating()
Start the heart beating.
Definition: MSContext.cpp:597
bool IsBeatingFinished() const
Whenever the heart beating is finished.
Definition: MSContext.cpp:364
void PlayedSessionFinished()
The played session is finished.
virtual void StopHeartBeating()
Stop the heart beating.
Definition: MSContext.cpp:623
QString GetRecordPath() const
Get the path of the record directory.
Definition: MSContext.cpp:302
virtual void Resume()
Resume the context.
Definition: MSContext.cpp:637
static void SetDebugStatus(bool new_status, bool global=false)
Set debug status.
Definition: MCLog.cpp:79
bool CPUProfiling
CPU profiling.
Definition: MSContext.hpp:553
ArgSearchResult FindArgument(const QString &arg, const QString &long_arg)
Find an argument.
Definition: MSContext.cpp:376
void UnregisterElement(MSElement &element)
Unregister an element.
Definition: MSContext.cpp:519
#define MC_NPRINT(...)
Print macro with normal letters without colors.
Definition: MCLog.hpp:51
static int GetTimerElapsedTime(const QString &id)
Get the elapsed time of a timer.
Definition: MSContext.cpp:734
void NewHeartBeat(int beat_id)
New heart beat.
void RegisterSessionStorage(MSSessionStorageInterface &storage)
Register a session storage.
Definition: MSContext.cpp:485
int GetPlayedBeats() const
Get the played beats.
Definition: MSContext.cpp:340
T MCRandComplex(const T &min, const T &max)
Get a random number generated with an advanced algorithm.
Definition: MCDefs.hpp:230
static void ResetTimer(const QString &id)
Reset a timer.
Definition: MSContext.cpp:712
void SetMaxBeats(int max_beats)
Set the limit of the beats.
Definition: MSContext.cpp:334
virtual bool PrepareSession()
Prepare a session.
Definition: MSContext.cpp:553
#define MC_BPRINT(color,...)
Print macro with bold letters.
Definition: MCLog.hpp:47
#define MC_DIR_SEPARATOR
Directory separator macro.
Definition: MCDefs.hpp:578
void HeartStopped()
The heart has been stopped.
QString GetPlaybackPath() const
Get the playback path.
bool HasRegisteredElements() const
Has registered elements.
Definition: MSContext.cpp:352
void SetPlaybackPath(const QString &play_path)
Set the path of the play directory.
Definition: MSContext.cpp:296
static void SetNewSeed(int seed=(int) time(nullptr))
Set a new global random seed based on the system time.
Definition: MCDefs.cpp:72
virtual void FinishSession()
Finish a session.
Definition: MSContext.cpp:584
void Finalize()
Finalize the storage operations.
void SetBeatDurationLimit(int new_limit)
Set the beat duration limit.
Definition: MSContext.cpp:547
QString GetPlaybackPath() const
Get the path of the play directory.
Definition: MSContext.cpp:290
QList< MSElement * > RegElements
Elements to be registered by the heart beat.
Definition: MSContext.hpp:551
~MSContext()
Class destructor.
Definition: MSContext.cpp:227
void RegisterStorage(MSSessionStorageInterface &storage)
Register a session storage.
MS::ElementType GetType() const
Get the type of the element.
Definition: MSElement.cpp:101
void Stop()
Stop the activities in the context.
QStringList ProgramArguments
Command line arguments.
Definition: MSContext.hpp:549
QString MSGetBasePath()
Get the base path.
Definition: MSDefs.cpp:45
MSContext(int &argc, char **argv, bool graphical_context=false)
Class constructor.
Definition: MSContext.cpp:163
void SetDefaultDebugItems(const QString &items)
Set default active debug items.
Definition: MSContext.cpp:284
virtual void Pause()
Pause the context.
Definition: MSContext.cpp:630
static void SetDebugFilter(const std::string &new_filter)
Set debug filter.
Definition: MCLog.cpp:98
#define MC_LOG(...)
Debug macro.
Definition: MCLog.hpp:41
static void StopTimer(const QString &id)
Stop a timer.
Definition: MSContext.cpp:690
QString GetRecordPath() const
Get the record path.
void RegisterElement(MSElement &element)
Register a new element.
Definition: MSContext.cpp:491
void RegisterElement(MSElement &object)
Register an element.
void SetRecordPath(const QString &record_path)
Set the record path.
void PrepareRecord()
Prepare the record of a new session.
static MSContext * GetInstance()
Get a static instance of the class.
Definition: MSContext.cpp:268
int GetMaxBeats() const
Get the limit of the beats.
Definition: MSContext.cpp:328
const QString SessionRuntimeTimerName
Session runtime timer name.
Definition: MSContext.hpp:559
static void SetDebugColorFilters(const std::string &new_color_filters)
Set debug color filters.
Definition: MCLog.cpp:112