MythTV  master
Groups.cpp
Go to the documentation of this file.
1 /* Groups.cpp
2 
3  Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either version 2
8  of the License, or (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18  Or, point your browser to http://www.gnu.org/copyleft/gpl.html
19 
20 */
21 
22 #include "Root.h"
23 #include "Groups.h"
24 #include "ASN1Codes.h"
25 #include "ParseNode.h"
26 #include "Ingredients.h"
27 #include "Programs.h"
28 #include "Variables.h"
29 #include "Presentable.h"
30 #include "Visible.h"
31 #include "Engine.h"
32 #include "Text.h"
33 #include "Bitmap.h"
34 #include "Stream.h"
35 #include "DynamicLineArt.h"
36 #include "Link.h"
37 #include "TokenGroup.h"
38 #include "Logging.h"
39 
41 {
42  while (!m_Timers.isEmpty())
43  {
44  delete m_Timers.takeFirst();
45  }
46 }
47 
49 {
50  engine->GetGroupId().Copy(""); // Set to empty before we start (just in case).
51  MHRoot::Initialise(p, engine);
52 
53  // Must be an external reference with an object number of zero.
55  {
56  MHERROR("Object reference for a group object must be zero and external");
57  }
58 
59  // Set the group id for the rest of the group to this.
61  // Some of the information is irrelevant.
62  // MHParseNode *pStdId = p->GetNamedArg(C_STANDARD_IDENTIFIER);
63  // MHParseNode *pStdVersion = p->GetNamedArg(C_STANDARD_VERSION);
64  // MHParseNode *pObjectInfo = p->GetNamedArg(C_OBJECT_INFORMATION);
65 
66  MHParseNode *pOnStartUp = p->GetNamedArg(C_ON_START_UP);
67 
68  if (pOnStartUp)
69  {
70  m_StartUp.Initialise(pOnStartUp, engine);
71  }
72 
73  MHParseNode *pOnCloseDown = p->GetNamedArg(C_ON_CLOSE_DOWN);
74 
75  if (pOnCloseDown)
76  {
77  m_CloseDown.Initialise(pOnCloseDown, engine);
78  }
79 
80  MHParseNode *pOriginalGCPrio = p->GetNamedArg(C_ORIGINAL_GC_PRIORITY);
81 
82  if (pOriginalGCPrio)
83  {
84  m_nOrigGCPriority = pOriginalGCPrio->GetArgN(0)->GetIntValue();
85  }
86 
87  // Ignore the other stuff at the moment.
88  MHParseNode *pItems = p->GetNamedArg(C_ITEMS);
89 
90  if (pItems == nullptr)
91  {
92  p->Failure("Missing :Items block");
93  return;
94  }
95 
96  for (int i = 0; i < pItems->GetArgCount(); i++)
97  {
98  MHParseNode *pItem = pItems->GetArgN(i);
99  MHIngredient *pIngredient = nullptr;
100 
101  try
102  {
103  // Generate the particular kind of ingredient.
104  switch (pItem->GetTagNo())
105  {
106  case C_RESIDENT_PROGRAM:
107  pIngredient = new MHResidentProgram;
108  break;
109  case C_REMOTE_PROGRAM:
110  pIngredient = new MHRemoteProgram;
111  break;
113  pIngredient = new MHInterChgProgram;
114  break;
115  case C_PALETTE:
116  pIngredient = new MHPalette;
117  break;
118  case C_FONT:
119  pIngredient = new MHFont;
120  break;
121  case C_CURSOR_SHAPE:
122  pIngredient = new MHCursorShape;
123  break;
124  case C_BOOLEAN_VARIABLE:
125  pIngredient = new MHBooleanVar;
126  break;
127  case C_INTEGER_VARIABLE:
128  pIngredient = new MHIntegerVar;
129  break;
131  pIngredient = new MHOctetStrVar;
132  break;
134  pIngredient = new MHObjectRefVar;
135  break;
137  pIngredient = new MHContentRefVar;
138  break;
139  case C_LINK:
140  pIngredient = new MHLink;
141  break;
142  case C_STREAM:
143  pIngredient = new MHStream;
144  break;
145  case C_BITMAP:
146  pIngredient = new MHBitmap;
147  break;
148  case C_LINE_ART:
149  pIngredient = new MHLineArt;
150  break;
151  case C_DYNAMIC_LINE_ART:
152  pIngredient = new MHDynamicLineArt;
153  break;
154  case C_RECTANGLE:
155  pIngredient = new MHRectangle;
156  break;
157  case C_HOTSPOT:
158  pIngredient = new MHHotSpot;
159  break;
160  case C_SWITCH_BUTTON:
161  pIngredient = new MHSwitchButton;
162  break;
163  case C_PUSH_BUTTON:
164  pIngredient = new MHPushButton;
165  break;
166  case C_TEXT:
167  pIngredient = new MHText;
168  break;
169  case C_ENTRY_FIELD:
170  pIngredient = new MHEntryField;
171  break;
172  case C_HYPER_TEXT:
173  pIngredient = new MHHyperText;
174  break;
175  case C_SLIDER:
176  pIngredient = new MHSlider;
177  break;
178  case C_TOKEN_GROUP:
179  pIngredient = new MHTokenGroup;
180  break;
181  case C_LIST_GROUP:
182  pIngredient = new MHListGroup;
183  break;
184  default:
185  MHLOG(MHLogWarning, QString("Unknown ingredient %1").arg(pItem->GetTagNo()));
186  // Future proofing: ignore any ingredients that we don't know about.
187  // Obviously these can only arise in the binary coding.
188  }
189 
190  if (pIngredient)
191  {
192  // Initialise it from its argments.
193  pIngredient->Initialise(pItem, engine);
194 
195  // Remember the highest numbered ingredient
196  if (pIngredient->m_ObjectReference.m_nObjectNo > m_nLastId)
197  {
198  m_nLastId = pIngredient->m_ObjectReference.m_nObjectNo;
199  }
200 
201  // Add it to the ingedients of this group.
202  m_Items.Append(pIngredient);
203  }
204  }
205  catch (...)
206  {
207  MHLOG(MHLogError, "ERROR in MHGroup::Initialise ingredient");
208  if (pIngredient && __mhlogStream)
209  pIngredient->PrintMe(__mhlogStream, 0);
210 
211  delete(pIngredient);
212  throw;
213  }
214  }
215 }
216 
217 void MHGroup::PrintMe(FILE *fd, int nTabs) const
218 {
219  MHRoot::PrintMe(fd, nTabs);
220 
221  if (m_StartUp.Size() != 0)
222  {
223  PrintTabs(fd, nTabs + 1);
224  fprintf(fd, ":OnStartUp (\n");
225  m_StartUp.PrintMe(fd, nTabs + 2);
226  PrintTabs(fd, nTabs + 2);
227  fprintf(fd, ")\n");
228  }
229 
230  if (m_CloseDown.Size() != 0)
231  {
232  PrintTabs(fd, nTabs + 1);
233  fprintf(fd, ":OnCloseDown (\n");
234  m_CloseDown.PrintMe(fd, nTabs + 2);
235  PrintTabs(fd, nTabs + 2);
236  fprintf(fd, ")\n");
237  }
238 
239  if (m_nOrigGCPriority != 127)
240  {
241  PrintTabs(fd, nTabs + 1);
242  fprintf(fd, ":OrigGCPriority %d\n", m_nOrigGCPriority);
243  }
244 
245  PrintTabs(fd, nTabs + 1);
246  fprintf(fd, ":Items ( \n");
247 
248  for (int i = 0; i < m_Items.Size(); i++)
249  {
250  m_Items.GetAt(i)->PrintMe(fd, nTabs + 2);
251  }
252 
253  PrintTabs(fd, nTabs + 1);
254  fprintf(fd, ")\n");
255 }
256 
257 // Preparation - sets up the run-time representation. Sets m_fAvailable and generates IsAvailable event.
259 {
260  // Prepare the ingredients first if they are initially active or are initially available programs.
261  for (int i = 0; i < m_Items.Size(); i++)
262  {
263  MHIngredient *pIngredient = m_Items.GetAt(i);
264 
265  if (pIngredient->InitiallyActive() || pIngredient->InitiallyAvailable())
266  {
267  pIngredient->Preparation(engine);
268  }
269  }
270 
271  MHRoot::Preparation(engine); // Prepare the root object and send the IsAvailable event.
272 }
273 
274 // Activation - starts running the object. Sets m_fRunning and generates IsRunning event.
276 {
277  if (m_fRunning)
278  {
279  return;
280  }
281 
282  MHRoot::Activation(engine);
283  // Run any start-up actions.
284  engine->AddActions(m_StartUp);
285  engine->RunActions();
286 
287  // Activate the ingredients in order.
288  for (int i = 0; i < m_Items.Size(); i++)
289  {
290  MHIngredient *pIngredient = m_Items.GetAt(i);
291 
292  if (pIngredient->InitiallyActive())
293  {
294  pIngredient->Activation(engine);
295  }
296  }
297 
298  m_fRunning = true;
299  // Record the time here. This is the basis for absolute times.
300  m_StartTime.start();
301  // Don't generate IsRunning here - that's done by the sub-classes.
302 }
303 
304 // Deactivation - stops running the object. Clears m_fRunning
306 {
307  if (! m_fRunning)
308  {
309  return;
310  }
311 
312  // Run any close-down actions.
313  engine->AddActions(m_CloseDown);
314  engine->RunActions();
315  MHRoot::Deactivation(engine);
316 }
317 
318 // Destruction - deletes the run-time representation. Clears m_fAvailable.
320 {
321  for (int i = m_Items.Size(); i > 0; i--)
322  {
323  m_Items.GetAt(i - 1)->Destruction(engine);
324  }
325 
326  MHRoot::Destruction(engine);
327 }
328 
329 // Return an object if its object ID matches (or if it's a stream, if it has a matching component).
331 {
333  {
334  return this;
335  }
336 
337  for (int i = m_Items.Size(); i > 0; i--)
338  {
339  MHRoot *pResult = m_Items.GetAt(i - 1)->FindByObjectNo(n);
340 
341  if (pResult)
342  {
343  return pResult;
344  }
345  }
346 
347  return nullptr;
348 }
349 
350 // Set up a timer or cancel a timer.
351 void MHGroup::SetTimer(int nTimerId, bool fAbsolute, int nMilliSecs, MHEngine * /*engine*/)
352 {
353  // First remove any existing timer with the same Id.
354  for (int i = 0; i < m_Timers.size(); i++)
355  {
356  MHTimer *pTimer = m_Timers.at(i);
357 
358  if (pTimer->m_nTimerId == nTimerId)
359  {
360  delete m_Timers.takeAt(i);
361  break;
362  }
363  }
364 
365  // If the time has passed we don't set up a timer.
366  QTime currentTime;
367  currentTime.start(); // Set current time
368 
369  if (nMilliSecs < 0 || (fAbsolute && m_StartTime.addMSecs(nMilliSecs) < currentTime))
370  {
371  return;
372  }
373 
374  MHTimer *pTimer = new MHTimer;
375  m_Timers.append(pTimer);
376  pTimer->m_nTimerId = nTimerId;
377 
378  if (fAbsolute)
379  {
380  pTimer->m_Time = m_StartTime.addMSecs(nMilliSecs);
381  }
382  else
383  {
384  pTimer->m_Time = currentTime.addMSecs(nMilliSecs);
385  }
386 }
387 
388 // Fire any timers that have passed.
390 {
391  QTime currentTime = QTime::currentTime(); // Get current time
392  QList<MHTimer *>::iterator it = m_Timers.begin();
393  MHTimer *pTimer;
394  int nMSecs = 0;
395 
396  while (it != m_Timers.end())
397  {
398  pTimer = *it;
399 
400  if (pTimer->m_Time <= currentTime) // Use <= rather than < here so we fire timers with zero time immediately.
401  {
402  // If the time has passed trigger the event and remove the timer from the queue.
403  engine->EventTriggered(this, EventTimerFired, pTimer->m_nTimerId);
404  delete pTimer;
405  it = m_Timers.erase(it);
406  }
407  else
408  {
409  // This has not yet expired. Set "nMSecs" to the earliest time we have.
410  int nMSecsToGo = currentTime.msecsTo(pTimer->m_Time);
411 
412  if (nMSecs == 0 || nMSecsToGo < nMSecs)
413  {
414  nMSecs = nMSecsToGo;
415  }
416 
417  ++it;
418  }
419  }
420 
421  return nMSecs;
422 }
423 
424 // Create a clone of the target and add it to the ingredients.
425 void MHGroup::MakeClone(MHRoot *pTarget, MHRoot *pRef, MHEngine *engine)
426 {
427  MHIngredient *pClone = pTarget->Clone(engine); // Clone it.
428  pClone->m_ObjectReference.m_GroupId.Copy(m_ObjectReference.m_GroupId); // Group id is the same as this.
429  pClone->m_ObjectReference.m_nObjectNo = ++m_nLastId; // Create a new object id.
430  m_Items.Append(pClone);
431  // Set the object reference result to the newly constructed ref.
432  pRef->SetVariableValue(pClone->m_ObjectReference);
433  pClone->Preparation(engine); // Prepare the clone.
434 }
435 
437 {
438  delete(m_pCurrentScene);
439 }
440 
442 {
443  MHGroup::Initialise(p, engine);
444  // OnSpawnCloseDown
446 
447  if (pOnSpawn)
448  {
449  m_OnSpawnCloseDown.Initialise(pOnSpawn, engine);
450  }
451 
452  // OnRestart
453  MHParseNode *pOnRestart = p->GetNamedArg(C_ON_RESTART);
454 
455  if (pOnRestart)
456  {
457  m_OnRestart.Initialise(pOnRestart, engine);
458  }
459 
460  // Default attributes. These are encoded in a group in binary.
462 
463  // but in the text form they're encoded in the Application block.
464  if (pDefattrs == nullptr)
465  {
466  pDefattrs = p;
467  }
468 
469  MHParseNode *pCharSet = pDefattrs->GetNamedArg(C_CHARACTER_SET);
470 
471  if (pCharSet)
472  {
473  m_nCharSet = pCharSet->GetArgN(0)->GetIntValue();
474  }
475 
476  // Colours
477  MHParseNode *pBGColour = pDefattrs->GetNamedArg(C_BACKGROUND_COLOUR);
478 
479  if (pBGColour)
480  {
481  m_BGColour.Initialise(pBGColour->GetArgN(0), engine);
482  }
483 
484  MHParseNode *pTextColour = pDefattrs->GetNamedArg(C_TEXT_COLOUR);
485 
486  if (pTextColour)
487  {
488  m_TextColour.Initialise(pTextColour->GetArgN(0), engine);
489  }
490 
491  MHParseNode *pButtonRefColour = pDefattrs->GetNamedArg(C_BUTTON_REF_COLOUR);
492 
493  if (pButtonRefColour)
494  {
495  m_ButtonRefColour.Initialise(pButtonRefColour->GetArgN(0), engine);
496  }
497 
498  MHParseNode *pHighlightRefColour = pDefattrs->GetNamedArg(C_HIGHLIGHT_REF_COLOUR);
499 
500  if (pHighlightRefColour)
501  {
502  m_HighlightRefColour.Initialise(pHighlightRefColour->GetArgN(0), engine);
503  }
504 
505  MHParseNode *pSliderRefColour = pDefattrs->GetNamedArg(C_SLIDER_REF_COLOUR);
506 
507  if (pSliderRefColour)
508  {
509  m_SliderRefColour.Initialise(pSliderRefColour->GetArgN(0), engine);
510  }
511 
512  // Content hooks
513  MHParseNode *pTextCHook = pDefattrs->GetNamedArg(C_TEXT_CONTENT_HOOK);
514 
515  if (pTextCHook)
516  {
517  m_nTextCHook = pTextCHook->GetArgN(0)->GetIntValue();
518  }
519 
520  MHParseNode *pIPCHook = pDefattrs->GetNamedArg(C_IP_CONTENT_HOOK);
521 
522  if (pIPCHook)
523  {
524  m_nIPCHook = pIPCHook->GetArgN(0)->GetIntValue();
525  }
526 
527  MHParseNode *pStrCHook = pDefattrs->GetNamedArg(C_STREAM_CONTENT_HOOK);
528 
529  if (pStrCHook)
530  {
531  m_nStrCHook = pStrCHook->GetArgN(0)->GetIntValue();
532  }
533 
534  MHParseNode *pBitmapCHook = pDefattrs->GetNamedArg(C_BITMAP_CONTENT_HOOK);
535 
536  if (pBitmapCHook)
537  {
538  m_nBitmapCHook = pBitmapCHook->GetArgN(0)->GetIntValue();
539  }
540 
541  MHParseNode *pLineArtCHook = pDefattrs->GetNamedArg(C_LINE_ART_CONTENT_HOOK);
542 
543  if (pLineArtCHook)
544  {
545  m_nLineArtCHook = pLineArtCHook->GetArgN(0)->GetIntValue();
546  }
547 
548  // Font. This is a little tricky. There are two attributes both called Font.
549  // In the binary notation the font here is encoded as 42 whereas the text form
550  // finds the first occurrence of :Font in the table and returns 13.
551  MHParseNode *pFont = pDefattrs->GetNamedArg(C_FONT2);
552 
553  if (pFont == nullptr)
554  {
555  pFont = pDefattrs->GetNamedArg(C_FONT);
556  }
557 
558  if (pFont)
559  {
560  m_Font.Initialise(pFont->GetArgN(0), engine);
561  }
562 
563  // Font attributes.
564  MHParseNode *pFontAttrs = pDefattrs->GetNamedArg(C_FONT_ATTRIBUTES);
565 
566  if (pFontAttrs)
567  {
568  pFontAttrs->GetArgN(0)->GetStringValue(m_FontAttrs);
569  }
570 }
571 
572 void MHApplication::PrintMe(FILE *fd, int nTabs) const
573 {
574  PrintTabs(fd, nTabs);
575  fprintf(fd, "{:Application ");
576  MHGroup::PrintMe(fd, nTabs);
577 
578  if (m_OnSpawnCloseDown.Size() != 0)
579  {
580  PrintTabs(fd, nTabs + 1);
581  fprintf(fd, ":OnSpawnCloseDown");
582  m_OnSpawnCloseDown.PrintMe(fd, nTabs + 1);
583  fprintf(fd, "\n");
584  }
585 
586  if (m_OnRestart.Size() != 0)
587  {
588  PrintTabs(fd, nTabs + 1);
589  fprintf(fd, ":OnRestart");
590  m_OnRestart.PrintMe(fd, nTabs + 1);
591  fprintf(fd, "\n");
592  }
593 
594  if (m_nCharSet > 0)
595  {
596  PrintTabs(fd, nTabs + 1);
597  fprintf(fd, ":CharacterSet %d\n", m_nCharSet);
598  }
599 
600  if (m_BGColour.IsSet())
601  {
602  PrintTabs(fd, nTabs + 1);
603  fprintf(fd, ":BackgroundColour ");
604  m_BGColour.PrintMe(fd, nTabs + 1);
605  fprintf(fd, "\n");
606  }
607 
608  if (m_nTextCHook > 0)
609  {
610  PrintTabs(fd, nTabs + 1);
611  fprintf(fd, ":TextCHook %d\n", m_nTextCHook);
612  }
613 
614  if (m_TextColour.IsSet())
615  {
616  PrintTabs(fd, nTabs + 1);
617  fprintf(fd, ":TextColour");
618  m_TextColour.PrintMe(fd, nTabs + 1);
619  fprintf(fd, "\n");
620  }
621 
622  if (m_Font.IsSet())
623  {
624  PrintTabs(fd, nTabs + 1);
625  fprintf(fd, ":Font ");
626  m_Font.PrintMe(fd, nTabs + 1);
627  fprintf(fd, "\n");
628  }
629 
630  if (m_FontAttrs.Size() > 0)
631  {
632  PrintTabs(fd, nTabs + 1);
633  fprintf(fd, ":FontAttributes ");
634  m_FontAttrs.PrintMe(fd, nTabs + 1);
635  fprintf(fd, "\n");
636  }
637 
638  if (m_nIPCHook > 0)
639  {
640  PrintTabs(fd, nTabs + 1);
641  fprintf(fd, ":InterchgPrgCHook %d\n", m_nIPCHook);
642  }
643 
644  if (m_nStrCHook > 0)
645  {
646  PrintTabs(fd, nTabs + 1);
647  fprintf(fd, ":StreamCHook %d\n", m_nStrCHook);
648  }
649 
650  if (m_nBitmapCHook > 0)
651  {
652  PrintTabs(fd, nTabs + 1);
653  fprintf(fd, ":BitmapCHook %d\n", m_nBitmapCHook);
654  }
655 
656  if (m_nLineArtCHook > 0)
657  {
658  PrintTabs(fd, nTabs + 1);
659  fprintf(fd, ":LineArtCHook %d\n", m_nLineArtCHook);
660  }
661 
662  if (m_ButtonRefColour.IsSet())
663  {
664  PrintTabs(fd, nTabs + 1);
665  fprintf(fd, ":ButtonRefColour ");
666  m_ButtonRefColour.PrintMe(fd, nTabs + 1);
667  fprintf(fd, "\n");
668  }
669 
671  {
672  PrintTabs(fd, nTabs + 1);
673  fprintf(fd, ":HighlightRefColour ");
674  m_HighlightRefColour.PrintMe(fd, nTabs + 1);
675  fprintf(fd, "\n");
676  }
677 
678  if (m_SliderRefColour.IsSet())
679  {
680  PrintTabs(fd, nTabs + 1);
681  fprintf(fd, ":SliderRefColour ");
682  m_SliderRefColour.PrintMe(fd, nTabs + 1);
683  fprintf(fd, "\n");
684  }
685 
686  fprintf(fd, "}\n");
687 }
688 
689 // This is a bit messy. The MHEG corrigendum says that we need to process OnRestart actions
690 // BEFORE generating IsRunning. That's important because TransitionTo etc are ignored during
691 // OnRestart but allowed in events triggered by IsRunning.
693 {
694  if (m_fRunning)
695  {
696  return;
697  }
698 
699  MHGroup::Activation(engine);
700 
701  if (m_fRestarting) // Set by Quit
702  {
703  engine->AddActions(m_OnRestart);
704  engine->RunActions();
705  }
706 
707  engine->EventTriggered(this, EventIsRunning);
708 }
709 
710 int MHApplication::FindOnStack(const MHRoot *pVis) // Returns the index on the stack or -1 if it's not there.
711 {
712  for (int i = 0; i < m_DisplayStack.Size(); i++)
713  {
714  if (m_DisplayStack.GetAt(i) == pVis)
715  {
716  return i;
717  }
718  }
719 
720  return -1; // Not there
721 }
722 
724 {
725  MHGroup::Initialise(p, engine);
726  // Event register.
727  MHParseNode *pInputEventReg = p->GetNamedArg(C_INPUT_EVENT_REGISTER);
728 
729  if (pInputEventReg)
730  {
731  m_nEventReg = pInputEventReg->GetArgN(0)->GetIntValue();
732  }
733 
734  // Co-ordinate system
736 
737  if (pSceneCoords)
738  {
739  m_nSceneCoordX = pSceneCoords->GetArgN(0)->GetIntValue();
740  m_nSceneCoordY = pSceneCoords->GetArgN(1)->GetIntValue();
741  }
742 
743  // Aspect ratio
744  MHParseNode *pAspectRatio = p->GetNamedArg(C_ASPECT_RATIO);
745 
746  if (pAspectRatio)
747  {
748  // Is the binary encoded as a sequence or a pair of arguments?
749  m_nAspectRatioW = pAspectRatio->GetArgN(0)->GetIntValue();
750  m_nAspectRatioH = pAspectRatio->GetArgN(1)->GetIntValue();
751  }
752 
753  // Moving cursor
754  MHParseNode *pMovingCursor = p->GetNamedArg(C_MOVING_CURSOR);
755 
756  if (pMovingCursor)
757  {
758  pMovingCursor->GetArgN(0)->GetBoolValue();
759  }
760 
761  // Next scene sequence: this is just a hint and isn't implemented
762 }
763 
764 void MHScene::PrintMe(FILE *fd, int nTabs) const
765 {
766  PrintTabs(fd, nTabs);
767  fprintf(fd, "{:Scene ");
768  MHGroup::PrintMe(fd, nTabs);
769  PrintTabs(fd, nTabs + 1);
770  fprintf(fd, ":InputEventReg %d\n", m_nEventReg);
771  PrintTabs(fd, nTabs + 1);
772  fprintf(fd, ":SceneCS %d %d\n", m_nSceneCoordX, m_nSceneCoordY);
773 
774  if (m_nAspectRatioW != 4 || m_nAspectRatioH != 3)
775  {
776  PrintTabs(fd, nTabs + 1);
777  fprintf(fd, ":AspectRatio %d %d\n", m_nAspectRatioW, m_nAspectRatioH);
778  }
779 
780  if (m_fMovingCursor)
781  {
782  PrintTabs(fd, nTabs + 1);
783  fprintf(fd, ":MovingCursor true\n");
784  }
785 
786  fprintf(fd, "}\n");
787 }
788 
790 {
791  if (m_fRunning)
792  {
793  return;
794  }
795 
796  MHGroup::Activation(engine);
797  engine->EventTriggered(this, EventIsRunning);
798 }
799 
800 // Action added in UK MHEG profile. It doesn't define a new internal attribute for this.
801 void MHScene::SetInputRegister(int nReg, MHEngine *engine)
802 {
803  m_nEventReg = nReg;
804  engine->SetInputRegister(nReg);
805 }
806 
807 
809 {
810  MHElemAction::Initialise(p, engine); // Target
811  m_EventSource.Initialise(p->GetArgN(1), engine);
812  m_EventType = (enum EventType)p->GetArgN(2)->GetEnumValue();
813 
814  if (p->GetArgCount() >= 4)
815  {
816  // TODO: We could check here that we only have bool, int or string and not object ref or content ref.
817  m_EventData.Initialise(p->GetArgN(3), engine);
818  }
819 }
820 
821 void MHSendEvent::PrintArgs(FILE *fd, int /*nTabs*/) const
822 {
823  m_EventSource.PrintMe(fd, 0);
824  QByteArray tmp = MHLink::EventTypeToString(m_EventType).toLatin1();
825  fprintf(fd, "%s", tmp.constData());
826  fprintf(fd, " ");
827 
829  {
830  m_EventData.PrintMe(fd, 0);
831  }
832 }
833 
835 {
836  // The target is always the current scene so we ignore it here.
837  MHObjectRef target, source;
838  m_Target.GetValue(target, engine); // TODO: Check this is the scene?
839  m_EventSource.GetValue(source, engine);
840 
841  // Generate the event.
843  {
844  engine->EventTriggered(engine->FindObject(source), m_EventType);
845  }
846  else
847  {
848  MHUnion data;
849  data.GetValueFrom(m_EventData, engine);
850  engine->EventTriggered(engine->FindObject(source), m_EventType, data);
851  }
852 }
853 
855 {
856  MHElemAction::Initialise(p, engine);
857  m_TimerId.Initialise(p->GetArgN(1), engine); // The timer id
858 
859  if (p->GetArgCount() > 2)
860  {
861  MHParseNode *pNewTimer = p->GetArgN(2);
862  m_TimerValue.Initialise(pNewTimer->GetSeqN(0), engine);
863 
864  if (pNewTimer->GetSeqCount() > 1)
865  {
866  m_TimerType = ST_TimerAbsolute; // May be absolute - depends on the value.
867  m_AbsFlag.Initialise(pNewTimer->GetSeqN(1), engine);
868  }
869  else
870  {
872  }
873  }
874 }
875 
876 void MHSetTimer::PrintArgs(FILE *fd, int /*nTabs*/) const
877 {
878  m_TimerId.PrintMe(fd, 0);
879 
880  if (m_TimerType != ST_NoNewTimer)
881  {
882  fprintf(fd, "( ");
883  m_TimerValue.PrintMe(fd, 0);
884 
886  {
887  m_AbsFlag.PrintMe(fd, 0);
888  }
889 
890  fprintf(fd, ") ");
891  }
892 }
893 
895 {
896  int nTimerId = m_TimerId.GetValue(engine);
897  bool fAbsolute = false; // Defaults to relative time.
898  int newTime = -1;
899 
900  switch (m_TimerType)
901  {
902  case ST_NoNewTimer:
903  fAbsolute = true;
904  newTime = -1;
905  break; // We treat an absolute time of -1 as "cancel"
906  case ST_TimerAbsolute:
907  fAbsolute = m_AbsFlag.GetValue(engine);
908  [[clang::fallthrough]];
909  case ST_TimerRelative:
910  newTime = m_TimerValue.GetValue(engine);
911  }
912 
913  Target(engine)->SetTimer(nTimerId, fAbsolute, newTime, engine);
914 }
915 
917 {
918  MHElemAction::Initialise(p, engine); // Target
919  m_Succeeded.Initialise(p->GetArgN(1), engine);
920  MHParseNode *pVarSeq = p->GetArgN(2);
921 
922  for (int i = 0; i < pVarSeq->GetSeqCount(); i++)
923  {
924  MHObjectRef *pVar = new MHObjectRef;
925  m_Variables.Append(pVar);
926  pVar->Initialise(pVarSeq->GetSeqN(i), engine);
927  }
928 
929  m_FileName.Initialise(p->GetArgN(3), engine);
930 }
931 
932 void MHPersistent::PrintArgs(FILE *fd, int nTabs) const
933 {
934  m_Succeeded.PrintMe(fd, nTabs);
935  fprintf(fd, " ( ");
936 
937  for (int i = 0; i < m_Variables.Size(); i++)
938  {
939  m_Variables.GetAt(i)->PrintMe(fd, 0);
940  }
941 
942  fprintf(fd, " ) ");
943  m_FileName.PrintMe(fd, nTabs);
944 }
945 
947 {
948  MHObjectRef target;
949  m_Target.GetValue(target, engine); // Get the target - this should always be the application
950  MHOctetString fileName;
951  m_FileName.GetValue(fileName, engine);
952  bool fResult = engine->LoadStorePersistent(m_fIsLoad, fileName, m_Variables);
953  engine->FindObject(m_Succeeded)->SetVariableValue(fResult);
954 }
955 
957 {
958  m_fIsTagged = false;
959  m_nConnectionTag = 0;
960  m_nTransitionEffect = -1;
961 }
962 
964 {
965  MHElemAction::Initialise(p, engine); // Target
966  // The next one may be present but NULL in binary.
967  if (p->GetArgCount() > 1)
968  {
969  MHParseNode *pCtag = p->GetArgN(1);
970 
971  if (pCtag->m_nNodeType == MHParseNode::PNInt)
972  {
973  m_fIsTagged = true;
974  m_nConnectionTag = pCtag->GetIntValue();
975  }
976  }
977 
978  if (p->GetArgCount() > 2)
979  {
980  MHParseNode *pTrEff = p->GetArgN(2);
981  m_nTransitionEffect = pTrEff->GetIntValue();
982  }
983 }
984 
985 void MHTransitionTo::PrintArgs(FILE *fd, int /*nTabs*/) const
986 {
987  if (m_fIsTagged)
988  {
989  fprintf(fd, " %d ", m_nConnectionTag);
990  }
991  else if (m_nTransitionEffect >= 0)
992  {
993  fprintf(fd, " NULL ");
994  }
995 
996  if (m_nTransitionEffect >= 0)
997  {
998  fprintf(fd, " %d", m_nTransitionEffect);
999  }
1000 }
1001 
1002 // Do the action - Transition to a new scene.
1004 {
1005  MHObjectRef target;
1006  m_Target.GetValue(target, engine); // Get the target
1007  engine->TransitionToScene(target);
1008 }
1009 
1011 {
1012  MHObjectRef target;
1013  m_Target.GetValue(target, engine);
1014  engine->Launch(target);
1015 }
1017 {
1018  engine->Quit();
1019 }
1021 {
1022  MHObjectRef target;
1023  m_Target.GetValue(target, engine);
1024  engine->Spawn(target);
1025 }
1027 {
1028  engine->LockScreen();
1029 }
1031 {
1032  engine->UnlockScreen();
1033 }
1034 
1036 {
1037  MHElemAction::Initialise(p, engine);
1038  m_Feature.Initialise(p->GetArgN(1), engine);
1039  m_Answer.Initialise(p->GetArgN(2), engine);
1040 }
1041 
1043 {
1044  // Ignore the target which isn't used.
1045  MHOctetString feature;
1046  m_Feature.GetValue(feature, engine);
1047  engine->FindObject(m_Answer)->SetVariableValue(engine->GetEngineSupport(feature));
1048 }
void Initialise(MHParseNode *p, MHEngine *engine)
#define C_DYNAMIC_LINE_ART
Definition: ASN1Codes.h:57
int m_nTransitionEffect
Definition: Groups.h:236
void Failure(const char *p)
Definition: ParseNode.cpp:43
void Activation(MHEngine *engine) override
Definition: Groups.cpp:789
void Preparation(MHEngine *engine) override
virtual void Destruction(MHEngine *engine)
Definition: Root.cpp:97
void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Groups.h:39
#define C_HYPER_TEXT
Definition: ASN1Codes.h:64
#define C_FONT2
Definition: ASN1Codes.h:75
QTime m_Time
Definition: Groups.h:42
void Deactivation(MHEngine *engine) override
Definition: Groups.cpp:305
#define C_LIST_GROUP
Definition: ASN1Codes.h:67
QList< MHTimer * > m_Timers
Definition: Groups.h:78
#define C_SWITCH_BUTTON
Definition: ASN1Codes.h:60
void PrintMe(FILE *fd, int nTabs) const override
#define MHERROR(__text)
Definition: Logging.h:42
bool GetValue(MHEngine *engine) const
MHObjectRef m_Answer
Definition: Groups.h:264
#define C_ON_CLOSE_DOWN
Definition: ASN1Codes.h:39
void PrintMe(FILE *fd, int nTabs) const
MHParameter m_EventData
Definition: Groups.h:183
MHOwnPtrSequence< MHObjectRef > m_Variables
Definition: Groups.h:220
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1042
void RunActions()
Definition: Engine.cpp:614
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1003
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1030
void PrintMe(FILE *fd, int nTabs) const
#define C_INPUT_EVENT_REGISTER
Definition: ASN1Codes.h:84
MHColour m_BGColour
Definition: Groups.h:132
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:723
virtual void SetVariableValue(const MHUnion &)
Definition: Root.h:101
MHGenericObjectRef m_Target
Definition: BaseActions.h:46
virtual bool InitiallyAvailable()
Definition: Ingredients.h:43
virtual MHRoot * FindByObjectNo(int n)
Definition: Root.cpp:115
#define C_CONTENT_REF_VARIABLE
Definition: ASN1Codes.h:52
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Root.cpp:38
MHRoot * Target(MHEngine *engine)
Definition: BaseActions.cpp:46
BASE GetAt(int i) const
Definition: BaseClasses.h:48
enum NodeType m_nNodeType
Definition: ParseNode.h:46
bool IsSet() const
Definition: BaseClasses.h:141
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:963
#define C_TEXT
Definition: ASN1Codes.h:62
void Initialise(MHParseNode *p, MHEngine *engine)
void Perform(MHEngine *engine) override
Definition: Groups.cpp:834
void TransitionToScene(const MHObjectRef &)
Definition: Engine.cpp:418
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:69
int m_nBitmapCHook
Definition: Groups.h:136
virtual bool InitiallyActive()
Definition: Ingredients.h:42
MHColour m_TextColour
Definition: Groups.h:132
MHScene * m_pCurrentScene
Definition: Groups.h:149
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:441
MHGenericObjectRef m_EventSource
Definition: Groups.h:181
MHOctetString m_FontAttrs
Definition: Groups.h:139
int CheckTimers(MHEngine *engine)
Definition: Groups.cpp:389
#define C_PALETTE
Definition: ASN1Codes.h:45
#define C_ASPECT_RATIO
Definition: ASN1Codes.h:86
MHOwnPtrSequence< MHIngredient > m_Items
Definition: Groups.h:70
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:85
void MakeClone(MHRoot *pTarget, MHRoot *pRef, MHEngine *engine) override
Definition: Groups.cpp:425
#define C_BITMAP_CONTENT_HOOK
Definition: ASN1Codes.h:79
enum MHParameter::ParamTypes m_Type
#define C_ITEMS
Definition: ASN1Codes.h:41
int GetValue(MHEngine *engine) const
void GetValue(MHOctetString &str, MHEngine *engine) const
void Perform(MHEngine *engine) override
Definition: Groups.cpp:946
#define C_RECTANGLE
Definition: ASN1Codes.h:58
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:764
#define C_STREAM_CONTENT_HOOK
Definition: ASN1Codes.h:78
bool Launch(const MHObjectRef &target, bool fIsSpawn=false)
Definition: Engine.cpp:273
int m_nCharSet
Definition: Groups.h:131
void PrintMe(FILE *fd, int nTabs) const
MHGenericInteger m_TimerValue
Definition: Groups.h:198
static guint32 * tmp
Definition: goom_core.c:35
void Initialise(MHParseNode *p, MHEngine *engine)
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:854
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
#define C_SCENE_COORDINATE_SYSTEM
Definition: ASN1Codes.h:85
void GetValueFrom(const MHParameter &value, MHEngine *engine)
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1026
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:48
void GetValue(MHObjectRef &ref, MHEngine *engine) const
#define C_OCTET_STRING_VARIABLE
Definition: ASN1Codes.h:50
int FindOnStack(const MHRoot *pVis)
Definition: Groups.cpp:710
void Initialise(MHParseNode *p, MHEngine *engine)
virtual MHIngredient * Clone(MHEngine *)
Definition: Root.h:91
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
MHFontBody m_Font
Definition: Groups.h:138
MHRoot * FindByObjectNo(int n) override
Definition: Groups.cpp:330
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:1035
int m_nLastId
Definition: Groups.h:81
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:572
MHParseNode * GetSeqN(int n)
Definition: ParseNode.cpp:152
void Copy(const MHOctetString &str)
#define C_BOOLEAN_VARIABLE
Definition: ASN1Codes.h:48
int Size() const
Definition: BaseClasses.h:117
int m_nIPCHook
Definition: Groups.h:134
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:49
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:876
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:985
MHGenericInteger m_TimerId
Definition: Groups.h:194
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:916
void Perform(MHEngine *engine) override
Definition: Groups.cpp:894
void Preparation(MHEngine *engine) override
Definition: Groups.cpp:258
int GetIntValue()
Definition: ParseNode.cpp:170
#define C_REMOTE_PROGRAM
Definition: ASN1Codes.h:43
FILE * __mhlogStream
Definition: Engine.cpp:1481
bool m_fMovingCursor
Definition: Groups.h:108
#define C_BUTTON_REF_COLOUR
Definition: ASN1Codes.h:81
#define C_INTERCHANGED_PROGRAM
Definition: ASN1Codes.h:44
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:93
int m_nStrCHook
Definition: Groups.h:135
bool LoadStorePersistent(bool fIsLoad, const MHOctetString &fileName, const MHSequence< MHObjectRef * > &variables)
Definition: Engine.cpp:1113
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:821
MHGenericOctetString m_Feature
Definition: Groups.h:263
virtual ~MHGroup()
Definition: Groups.cpp:40
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
MHParseNode * GetNamedArg(int nTag)
Definition: ParseNode.cpp:110
enum EventType m_EventType
Definition: Groups.h:182
#define C_LINE_ART_CONTENT_HOOK
Definition: ASN1Codes.h:80
void PrintMe(FILE *fd, int nTabs) const
#define C_TEXT_COLOUR
Definition: ASN1Codes.h:74
QTime m_StartTime
Definition: Groups.h:77
int m_nTextCHook
Definition: Groups.h:133
#define C_FONT
Definition: ASN1Codes.h:46
void Initialise(MHParseNode *p, MHEngine *engine)
#define C_TEXT_CONTENT_HOOK
Definition: ASN1Codes.h:73
Definition: Root.h:43
void PrintMe(FILE *fd, int nTabs) const
void PrintMe(FILE *fd, int nTabs) const
MHObjectRef m_Succeeded
Definition: Groups.h:219
bool m_fRunning
Definition: Root.h:208
MHObjectRef m_ObjectReference
Definition: Root.h:203
#define C_BACKGROUND_COLOUR
Definition: ASN1Codes.h:72
int FILE
Definition: mythburn.py:110
MHActionSequence m_OnRestart
Definition: Groups.h:129
#define C_TOKEN_GROUP
Definition: ASN1Codes.h:66
virtual ~MHApplication()
Definition: Groups.cpp:436
int m_nTimerId
Definition: Groups.h:41
virtual void SetTimer(int, bool, int, MHEngine *)
Definition: Root.h:79
void Destruction(MHEngine *engine) override
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1010
int m_nEventReg
Definition: Groups.h:100
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1020
bool IsSet() const
Definition: BaseClasses.h:305
bool m_fIsLoad
Definition: Groups.h:218
MHActionSequence m_StartUp
Definition: Groups.h:69
MHColour m_ButtonRefColour
Definition: Groups.h:132
MHActionSequence m_OnSpawnCloseDown
Definition: Groups.h:129
#define C_LINK
Definition: ASN1Codes.h:53
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:932
int m_nSceneCoordX
Definition: Groups.h:101
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Root.cpp:30
void Destruction(MHEngine *engine) override
Definition: Groups.cpp:319
#define C_MOVING_CURSOR
Definition: ASN1Codes.h:87
void UnlockScreen()
Definition: Engine.cpp:907
void Initialise(MHParseNode *p, MHEngine *engine)
MHRoot * FindObject(const MHObjectRef &oRef, bool failOnNotFound=true)
Definition: Engine.cpp:575
int GetEnumValue()
Definition: ParseNode.cpp:181
#define C_PUSH_BUTTON
Definition: ASN1Codes.h:61
bool m_fIsTagged
Definition: Groups.h:234
#define C_ON_START_UP
Definition: ASN1Codes.h:38
void SetInputRegister(int nReg, MHEngine *engine) override
Definition: Groups.cpp:801
#define C_DEFAULT_ATTRIBUTES
Definition: ASN1Codes.h:70
void PrintMe(FILE *fd, int nTabs) const
#define MHLOG(__level, __text)
Definition: Logging.h:36
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: BaseActions.cpp:31
#define C_INTEGER_VARIABLE
Definition: ASN1Codes.h:49
int GetSeqCount()
Definition: ParseNode.cpp:141
int GetArgCount()
Definition: ParseNode.cpp:60
Definition: Text.h:37
MHOctetString & GetGroupId()
Definition: Engine.h:152
#define C_ON_SPAWN_CLOSE_DOWN
Definition: ASN1Codes.h:68
bool GetBoolValue()
Definition: ParseNode.cpp:192
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1016
#define C_FONT_ATTRIBUTES
Definition: ASN1Codes.h:76
MHActionSequence m_CloseDown
Definition: Groups.h:69
void Initialise(MHParseNode *p, MHEngine *engine)
MHOctetString m_GroupId
Definition: BaseClasses.h:167
void Activation(MHEngine *engine) override
Definition: Groups.cpp:692
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Actions.cpp:468
void Quit()
Definition: Engine.cpp:377
void SetTimer(int nTimerId, bool fAbsolute, int nMilliSecs, MHEngine *) override
Definition: Groups.cpp:351
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
void Spawn(const MHObjectRef &target)
Definition: Engine.h:84
#define C_LINE_ART
Definition: ASN1Codes.h:56
MHSequence< MHVisible * > m_DisplayStack
Definition: Groups.h:146
int GetTagNo()
Definition: ParseNode.cpp:49
MHGenericBoolean m_AbsFlag
Definition: Groups.h:199
MHColour m_HighlightRefColour
Definition: Groups.h:132
void SetInputRegister(int nReg)
Definition: Engine.cpp:519
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:217
EventType
Definition: Root.h:33
void LockScreen()
Definition: Engine.h:109
#define C_SLIDER_REF_COLOUR
Definition: ASN1Codes.h:83
void Append(BASE b)
Definition: BaseClasses.h:62
int m_nAspectRatioW
Definition: Groups.h:106
#define C_ENTRY_FIELD
Definition: ASN1Codes.h:63
#define C_ORIGINAL_GC_PRIORITY
Definition: ASN1Codes.h:40
#define C_STREAM
Definition: ASN1Codes.h:54
int m_nLineArtCHook
Definition: Groups.h:137
bool m_fRestarting
Definition: Groups.h:150
#define C_BITMAP
Definition: ASN1Codes.h:55
int Size() const
Definition: BaseClasses.h:46
#define C_CURSOR_SHAPE
Definition: ASN1Codes.h:47
MHGenericOctetString m_FileName
Definition: Groups.h:221
int m_nSceneCoordY
Definition: Groups.h:102
#define C_HIGHLIGHT_REF_COLOUR
Definition: ASN1Codes.h:82
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:726
void PrintMe(FILE *fd, int nTabs) const
#define C_CHARACTER_SET
Definition: ASN1Codes.h:71
void PrintMe(FILE *fd, int nTabs) const
#define C_HOTSPOT
Definition: ASN1Codes.h:59
#define C_OBJECT_REF_VARIABLE
Definition: ASN1Codes.h:51
#define C_SLIDER
Definition: ASN1Codes.h:65
enum MHSetTimer::@9 m_TimerType
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:808
#define C_ON_RESTART
Definition: ASN1Codes.h:69
int m_nConnectionTag
Definition: Groups.h:235
virtual void Preparation(MHEngine *engine)
Definition: Root.cpp:52
int m_nOrigGCPriority
Definition: Groups.h:68
void Activation(MHEngine *engine) override
Definition: Groups.cpp:275
#define C_RESIDENT_PROGRAM
Definition: ASN1Codes.h:42
bool GetEngineSupport(const MHOctetString &feature)
Definition: Engine.cpp:1191
#define C_IP_CONTENT_HOOK
Definition: ASN1Codes.h:77
int m_nAspectRatioH
Definition: Groups.h:107
MHColour m_SliderRefColour
Definition: Groups.h:132