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
25#include <algorithm>
26
27#include "ASN1Codes.h"
28#include "ParseNode.h"
29#include "Ingredients.h"
30#include "Programs.h"
31#include "Variables.h"
32#include "Presentable.h"
33#include "Visible.h"
34#include "Engine.h"
35#include "Text.h"
36#include "Bitmap.h"
37#include "Stream.h"
38#include "DynamicLineArt.h"
39#include "Link.h"
40#include "TokenGroup.h"
41#include "Logging.h"
42
44{
45 while (!m_timers.isEmpty())
46 {
47 delete m_timers.takeFirst();
48 }
49}
50
52{
53 engine->GetGroupId().Copy(""); // Set to empty before we start (just in case).
54 MHRoot::Initialise(p, engine);
55
56 // Must be an external reference with an object number of zero.
58 {
59 MHERROR("Object reference for a group object must be zero and external");
60 }
61
62 // Set the group id for the rest of the group to this.
64 // Some of the information is irrelevant.
65 // MHParseNode *pStdId = p->GetNamedArg(C_STANDARD_IDENTIFIER);
66 // MHParseNode *pStdVersion = p->GetNamedArg(C_STANDARD_VERSION);
67 // MHParseNode *pObjectInfo = p->GetNamedArg(C_OBJECT_INFORMATION);
68
69 MHParseNode *pOnStartUp = p->GetNamedArg(C_ON_START_UP);
70
71 if (pOnStartUp)
72 {
73 m_startUp.Initialise(pOnStartUp, engine);
74 }
75
76 MHParseNode *pOnCloseDown = p->GetNamedArg(C_ON_CLOSE_DOWN);
77
78 if (pOnCloseDown)
79 {
80 m_closeDown.Initialise(pOnCloseDown, engine);
81 }
82
83 MHParseNode *pOriginalGCPrio = p->GetNamedArg(C_ORIGINAL_GC_PRIORITY);
84
85 if (pOriginalGCPrio)
86 {
87 m_nOrigGCPriority = pOriginalGCPrio->GetArgN(0)->GetIntValue();
88 }
89
90 // Ignore the other stuff at the moment.
91 MHParseNode *pItems = p->GetNamedArg(C_ITEMS);
92
93 if (pItems == nullptr)
94 {
95 MHParseNode::Failure("Missing :Items block");
96 return;
97 }
98
99 for (int i = 0; i < pItems->GetArgCount(); i++)
100 {
101 MHParseNode *pItem = pItems->GetArgN(i);
102 MHIngredient *pIngredient = nullptr;
103
104 try
105 {
106 // Generate the particular kind of ingredient.
107 switch (pItem->GetTagNo())
108 {
110 pIngredient = new MHResidentProgram;
111 break;
112 case C_REMOTE_PROGRAM:
113 pIngredient = new MHRemoteProgram;
114 break;
116 pIngredient = new MHInterChgProgram;
117 break;
118 case C_PALETTE:
119 pIngredient = new MHPalette;
120 break;
121 case C_FONT:
122 pIngredient = new MHFont;
123 break;
124 case C_CURSOR_SHAPE:
125 pIngredient = new MHCursorShape;
126 break;
128 pIngredient = new MHBooleanVar;
129 break;
131 pIngredient = new MHIntegerVar;
132 break;
134 pIngredient = new MHOctetStrVar;
135 break;
137 pIngredient = new MHObjectRefVar;
138 break;
140 pIngredient = new MHContentRefVar;
141 break;
142 case C_LINK:
143 pIngredient = new MHLink;
144 break;
145 case C_STREAM:
146 pIngredient = new MHStream;
147 break;
148 case C_BITMAP:
149 pIngredient = new MHBitmap;
150 break;
151 case C_LINE_ART:
152 pIngredient = new MHLineArt;
153 break;
155 pIngredient = new MHDynamicLineArt;
156 break;
157 case C_RECTANGLE:
158 pIngredient = new MHRectangle;
159 break;
160 case C_HOTSPOT:
161 pIngredient = new MHHotSpot;
162 break;
163 case C_SWITCH_BUTTON:
164 pIngredient = new MHSwitchButton;
165 break;
166 case C_PUSH_BUTTON:
167 pIngredient = new MHPushButton;
168 break;
169 case C_TEXT:
170 pIngredient = new MHText;
171 break;
172 case C_ENTRY_FIELD:
173 pIngredient = new MHEntryField;
174 break;
175 case C_HYPER_TEXT:
176 pIngredient = new MHHyperText;
177 break;
178 case C_SLIDER:
179 pIngredient = new MHSlider;
180 break;
181 case C_TOKEN_GROUP:
182 pIngredient = new MHTokenGroup;
183 break;
184 case C_LIST_GROUP:
185 pIngredient = new MHListGroup;
186 break;
187 default:
188 MHLOG(MHLogWarning, QString("Unknown ingredient %1").arg(pItem->GetTagNo()));
189 // Future proofing: ignore any ingredients that we don't know about.
190 // Obviously these can only arise in the binary coding.
191 }
192
193 if (pIngredient)
194 {
195 // Initialise it from its argments.
196 pIngredient->Initialise(pItem, engine);
197
198 // Remember the highest numbered ingredient
199 m_nLastId = std::max(pIngredient->m_ObjectReference.m_nObjectNo, m_nLastId);
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 && gMHLogStream)
209 pIngredient->PrintMe(gMHLogStream, 0);
210
211 delete(pIngredient);
212 throw;
213 }
214 }
215}
216
217void 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 // Start the timer here. This is the basis for expiration..
300 m_runTime.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.
351void 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 if (nMilliSecs < 0 || (fAbsolute && m_runTime.hasExpired(nMilliSecs)))
367 {
368 return;
369 }
370
371 auto *pTimer = new MHTimer;
372 m_timers.append(pTimer);
373 pTimer->m_nTimerId = nTimerId;
374
375 if (fAbsolute)
376 {
377 QTime startTime = QTime::currentTime().addMSecs(-m_runTime.elapsed());
378 pTimer->m_Time = startTime.addMSecs(nMilliSecs);
379 }
380 else
381 {
382 pTimer->m_Time = QTime::currentTime().addMSecs(nMilliSecs);
383 }
384}
385
386// Fire any timers that have passed.
387std::chrono::milliseconds MHGroup::CheckTimers(MHEngine *engine)
388{
389 QTime currentTime = QTime::currentTime(); // Get current time
390 QList<MHTimer *>::iterator it = m_timers.begin();
391 std::chrono::milliseconds nMSecs = 0ms;
392
393 while (it != m_timers.end())
394 {
395 MHTimer *pTimer = *it;
396
397 if (pTimer->m_Time <= currentTime) // Use <= rather than < here so we fire timers with zero time immediately.
398 {
399 // If the time has passed trigger the event and remove the timer from the queue.
400 engine->EventTriggered(this, EventTimerFired, pTimer->m_nTimerId);
401 delete pTimer;
402 it = m_timers.erase(it);
403 }
404 else
405 {
406 // This has not yet expired. Set "nMSecs" to the earliest time we have.
407 auto nMSecsToGo = std::chrono::milliseconds(currentTime.msecsTo(pTimer->m_Time));
408
409 if (nMSecs == 0ms || nMSecsToGo < nMSecs)
410 {
411 nMSecs = nMSecsToGo;
412 }
413
414 ++it;
415 }
416 }
417
418 return nMSecs;
419}
420
421// Create a clone of the target and add it to the ingredients.
422void MHGroup::MakeClone(MHRoot *pTarget, MHRoot *pRef, MHEngine *engine)
423{
424 MHIngredient *pClone = pTarget->Clone(engine); // Clone it.
425 pClone->m_ObjectReference.m_groupId.Copy(m_ObjectReference.m_groupId); // Group id is the same as this.
426 pClone->m_ObjectReference.m_nObjectNo = ++m_nLastId; // Create a new object id.
427 m_items.Append(pClone);
428 // Set the object reference result to the newly constructed ref.
429 pRef->SetVariableValue(pClone->m_ObjectReference);
430 pClone->Preparation(engine); // Prepare the clone.
431}
432
434{
435 delete(m_pCurrentScene);
436}
437
439{
440 MHGroup::Initialise(p, engine);
441 // OnSpawnCloseDown
442 MHParseNode *pOnSpawn = p->GetNamedArg(C_ON_SPAWN_CLOSE_DOWN);
443
444 if (pOnSpawn)
445 {
446 m_onSpawnCloseDown.Initialise(pOnSpawn, engine);
447 }
448
449 // OnRestart
450 MHParseNode *pOnRestart = p->GetNamedArg(C_ON_RESTART);
451
452 if (pOnRestart)
453 {
454 m_onRestart.Initialise(pOnRestart, engine);
455 }
456
457 // Default attributes. These are encoded in a group in binary.
458 MHParseNode *pDefattrs = p->GetNamedArg(C_DEFAULT_ATTRIBUTES);
459
460 // but in the text form they're encoded in the Application block.
461 if (pDefattrs == nullptr)
462 {
463 pDefattrs = p;
464 }
465
466 MHParseNode *pCharSet = pDefattrs->GetNamedArg(C_CHARACTER_SET);
467
468 if (pCharSet)
469 {
470 m_nCharSet = pCharSet->GetArgN(0)->GetIntValue();
471 }
472
473 // Colours
474 MHParseNode *pBGColour = pDefattrs->GetNamedArg(C_BACKGROUND_COLOUR);
475
476 if (pBGColour)
477 {
478 m_bgColour.Initialise(pBGColour->GetArgN(0), engine);
479 }
480
481 MHParseNode *pTextColour = pDefattrs->GetNamedArg(C_TEXT_COLOUR);
482
483 if (pTextColour)
484 {
485 m_textColour.Initialise(pTextColour->GetArgN(0), engine);
486 }
487
488 MHParseNode *pButtonRefColour = pDefattrs->GetNamedArg(C_BUTTON_REF_COLOUR);
489
490 if (pButtonRefColour)
491 {
492 m_buttonRefColour.Initialise(pButtonRefColour->GetArgN(0), engine);
493 }
494
495 MHParseNode *pHighlightRefColour = pDefattrs->GetNamedArg(C_HIGHLIGHT_REF_COLOUR);
496
497 if (pHighlightRefColour)
498 {
499 m_highlightRefColour.Initialise(pHighlightRefColour->GetArgN(0), engine);
500 }
501
502 MHParseNode *pSliderRefColour = pDefattrs->GetNamedArg(C_SLIDER_REF_COLOUR);
503
504 if (pSliderRefColour)
505 {
506 m_sliderRefColour.Initialise(pSliderRefColour->GetArgN(0), engine);
507 }
508
509 // Content hooks
510 MHParseNode *pTextCHook = pDefattrs->GetNamedArg(C_TEXT_CONTENT_HOOK);
511
512 if (pTextCHook)
513 {
514 m_nTextCHook = pTextCHook->GetArgN(0)->GetIntValue();
515 }
516
517 MHParseNode *pIPCHook = pDefattrs->GetNamedArg(C_IP_CONTENT_HOOK);
518
519 if (pIPCHook)
520 {
521 m_nIPCHook = pIPCHook->GetArgN(0)->GetIntValue();
522 }
523
524 MHParseNode *pStrCHook = pDefattrs->GetNamedArg(C_STREAM_CONTENT_HOOK);
525
526 if (pStrCHook)
527 {
528 m_nStrCHook = pStrCHook->GetArgN(0)->GetIntValue();
529 }
530
531 MHParseNode *pBitmapCHook = pDefattrs->GetNamedArg(C_BITMAP_CONTENT_HOOK);
532
533 if (pBitmapCHook)
534 {
535 m_nBitmapCHook = pBitmapCHook->GetArgN(0)->GetIntValue();
536 }
537
538 MHParseNode *pLineArtCHook = pDefattrs->GetNamedArg(C_LINE_ART_CONTENT_HOOK);
539
540 if (pLineArtCHook)
541 {
542 m_nLineArtCHook = pLineArtCHook->GetArgN(0)->GetIntValue();
543 }
544
545 // Font. This is a little tricky. There are two attributes both called Font.
546 // In the binary notation the font here is encoded as 42 whereas the text form
547 // finds the first occurrence of :Font in the table and returns 13.
548 MHParseNode *pFont = pDefattrs->GetNamedArg(C_FONT2);
549
550 if (pFont == nullptr)
551 {
552 pFont = pDefattrs->GetNamedArg(C_FONT);
553 }
554
555 if (pFont)
556 {
557 m_font.Initialise(pFont->GetArgN(0), engine);
558 }
559
560 // Font attributes.
561 MHParseNode *pFontAttrs = pDefattrs->GetNamedArg(C_FONT_ATTRIBUTES);
562
563 if (pFontAttrs)
564 {
565 pFontAttrs->GetArgN(0)->GetStringValue(m_fontAttrs);
566 }
567}
568
569void MHApplication::PrintMe(FILE *fd, int nTabs) const
570{
571 PrintTabs(fd, nTabs);
572 fprintf(fd, "{:Application ");
573 MHGroup::PrintMe(fd, nTabs);
574
575 if (m_onSpawnCloseDown.Size() != 0)
576 {
577 PrintTabs(fd, nTabs + 1);
578 fprintf(fd, ":OnSpawnCloseDown");
579 m_onSpawnCloseDown.PrintMe(fd, nTabs + 1);
580 fprintf(fd, "\n");
581 }
582
583 if (m_onRestart.Size() != 0)
584 {
585 PrintTabs(fd, nTabs + 1);
586 fprintf(fd, ":OnRestart");
587 m_onRestart.PrintMe(fd, nTabs + 1);
588 fprintf(fd, "\n");
589 }
590
591 if (m_nCharSet > 0)
592 {
593 PrintTabs(fd, nTabs + 1);
594 fprintf(fd, ":CharacterSet %d\n", m_nCharSet);
595 }
596
597 if (m_bgColour.IsSet())
598 {
599 PrintTabs(fd, nTabs + 1);
600 fprintf(fd, ":BackgroundColour ");
601 m_bgColour.PrintMe(fd, nTabs + 1);
602 fprintf(fd, "\n");
603 }
604
605 if (m_nTextCHook > 0)
606 {
607 PrintTabs(fd, nTabs + 1);
608 fprintf(fd, ":TextCHook %d\n", m_nTextCHook);
609 }
610
611 if (m_textColour.IsSet())
612 {
613 PrintTabs(fd, nTabs + 1);
614 fprintf(fd, ":TextColour");
615 m_textColour.PrintMe(fd, nTabs + 1);
616 fprintf(fd, "\n");
617 }
618
619 if (m_font.IsSet())
620 {
621 PrintTabs(fd, nTabs + 1);
622 fprintf(fd, ":Font ");
623 m_font.PrintMe(fd, nTabs + 1);
624 fprintf(fd, "\n");
625 }
626
627 if (m_fontAttrs.Size() > 0)
628 {
629 PrintTabs(fd, nTabs + 1);
630 fprintf(fd, ":FontAttributes ");
631 m_fontAttrs.PrintMe(fd, nTabs + 1);
632 fprintf(fd, "\n");
633 }
634
635 if (m_nIPCHook > 0)
636 {
637 PrintTabs(fd, nTabs + 1);
638 fprintf(fd, ":InterchgPrgCHook %d\n", m_nIPCHook);
639 }
640
641 if (m_nStrCHook > 0)
642 {
643 PrintTabs(fd, nTabs + 1);
644 fprintf(fd, ":StreamCHook %d\n", m_nStrCHook);
645 }
646
647 if (m_nBitmapCHook > 0)
648 {
649 PrintTabs(fd, nTabs + 1);
650 fprintf(fd, ":BitmapCHook %d\n", m_nBitmapCHook);
651 }
652
653 if (m_nLineArtCHook > 0)
654 {
655 PrintTabs(fd, nTabs + 1);
656 fprintf(fd, ":LineArtCHook %d\n", m_nLineArtCHook);
657 }
658
660 {
661 PrintTabs(fd, nTabs + 1);
662 fprintf(fd, ":ButtonRefColour ");
663 m_buttonRefColour.PrintMe(fd, nTabs + 1);
664 fprintf(fd, "\n");
665 }
666
668 {
669 PrintTabs(fd, nTabs + 1);
670 fprintf(fd, ":HighlightRefColour ");
671 m_highlightRefColour.PrintMe(fd, nTabs + 1);
672 fprintf(fd, "\n");
673 }
674
676 {
677 PrintTabs(fd, nTabs + 1);
678 fprintf(fd, ":SliderRefColour ");
679 m_sliderRefColour.PrintMe(fd, nTabs + 1);
680 fprintf(fd, "\n");
681 }
682
683 fprintf(fd, "}\n");
684}
685
686// This is a bit messy. The MHEG corrigendum says that we need to process OnRestart actions
687// BEFORE generating IsRunning. That's important because TransitionTo etc are ignored during
688// OnRestart but allowed in events triggered by IsRunning.
690{
691 if (m_fRunning)
692 {
693 return;
694 }
695
696 MHGroup::Activation(engine);
697
698 if (m_fRestarting) // Set by Quit
699 {
700 engine->AddActions(m_onRestart);
701 engine->RunActions();
702 }
703
704 engine->EventTriggered(this, EventIsRunning);
705}
706
707int MHApplication::FindOnStack(const MHRoot *pVis) // Returns the index on the stack or -1 if it's not there.
708{
709 for (int i = 0; i < m_displayStack.Size(); i++)
710 {
711 if (m_displayStack.GetAt(i) == pVis)
712 {
713 return i;
714 }
715 }
716
717 return -1; // Not there
718}
719
721{
722 MHGroup::Initialise(p, engine);
723 // Event register.
724 MHParseNode *pInputEventReg = p->GetNamedArg(C_INPUT_EVENT_REGISTER);
725
726 if (pInputEventReg)
727 {
728 m_nEventReg = pInputEventReg->GetArgN(0)->GetIntValue();
729 }
730
731 // Co-ordinate system
732 MHParseNode *pSceneCoords = p->GetNamedArg(C_SCENE_COORDINATE_SYSTEM);
733
734 if (pSceneCoords)
735 {
736 m_nSceneCoordX = pSceneCoords->GetArgN(0)->GetIntValue();
737 m_nSceneCoordY = pSceneCoords->GetArgN(1)->GetIntValue();
738 }
739
740 // Aspect ratio
741 MHParseNode *pAspectRatio = p->GetNamedArg(C_ASPECT_RATIO);
742
743 if (pAspectRatio)
744 {
745 // Is the binary encoded as a sequence or a pair of arguments?
746 m_nAspectRatioW = pAspectRatio->GetArgN(0)->GetIntValue();
747 m_nAspectRatioH = pAspectRatio->GetArgN(1)->GetIntValue();
748 }
749
750 // Moving cursor
751 MHParseNode *pMovingCursor = p->GetNamedArg(C_MOVING_CURSOR);
752
753 if (pMovingCursor)
754 {
755 pMovingCursor->GetArgN(0)->GetBoolValue();
756 }
757
758 // Next scene sequence: this is just a hint and isn't implemented
759}
760
761void MHScene::PrintMe(FILE *fd, int nTabs) const
762{
763 PrintTabs(fd, nTabs);
764 fprintf(fd, "{:Scene ");
765 MHGroup::PrintMe(fd, nTabs);
766 PrintTabs(fd, nTabs + 1);
767 fprintf(fd, ":InputEventReg %d\n", m_nEventReg);
768 PrintTabs(fd, nTabs + 1);
769 fprintf(fd, ":SceneCS %d %d\n", m_nSceneCoordX, m_nSceneCoordY);
770
771 if (m_nAspectRatioW != 4 || m_nAspectRatioH != 3)
772 {
773 PrintTabs(fd, nTabs + 1);
774 fprintf(fd, ":AspectRatio %d %d\n", m_nAspectRatioW, m_nAspectRatioH);
775 }
776
777 if (m_fMovingCursor)
778 {
779 PrintTabs(fd, nTabs + 1);
780 fprintf(fd, ":MovingCursor true\n");
781 }
782
783 fprintf(fd, "}\n");
784}
785
787{
788 if (m_fRunning)
789 {
790 return;
791 }
792
793 MHGroup::Activation(engine);
794 engine->EventTriggered(this, EventIsRunning);
795}
796
797// Action added in UK MHEG profile. It doesn't define a new internal attribute for this.
798void MHScene::SetInputRegister(int nReg, MHEngine *engine)
799{
800 m_nEventReg = nReg;
801 engine->SetInputRegister(nReg);
802}
803
804
806{
807 MHElemAction::Initialise(p, engine); // Target
808 m_eventSource.Initialise(p->GetArgN(1), engine);
809 m_eventType = (enum EventType)p->GetArgN(2)->GetEnumValue();
810
811 if (p->GetArgCount() >= 4)
812 {
813 // TODO: We could check here that we only have bool, int or string and not object ref or content ref.
814 m_eventData.Initialise(p->GetArgN(3), engine);
815 }
816}
817
818void MHSendEvent::PrintArgs(FILE *fd, int /*nTabs*/) const
819{
820 m_eventSource.PrintMe(fd, 0);
821 QByteArray tmp = MHLink::EventTypeToString(m_eventType).toLatin1();
822 fprintf(fd, "%s", tmp.constData());
823 fprintf(fd, " ");
824
825 if (m_eventData.m_Type != MHParameter::P_Null)
826 {
827 m_eventData.PrintMe(fd, 0);
828 }
829}
830
832{
833 // The target is always the current scene so we ignore it here.
834 MHObjectRef target;
835 MHObjectRef source;
836 m_target.GetValue(target, engine); // TODO: Check this is the scene?
837 m_eventSource.GetValue(source, engine);
838
839 // Generate the event.
840 if (m_eventData.m_Type == MHParameter::P_Null)
841 {
842 engine->EventTriggered(engine->FindObject(source), m_eventType);
843 }
844 else
845 {
846 MHUnion data;
847 data.GetValueFrom(m_eventData, engine);
848 engine->EventTriggered(engine->FindObject(source), m_eventType, data);
849 }
850}
851
853{
855 m_timerId.Initialise(p->GetArgN(1), engine); // The timer id
856
857 if (p->GetArgCount() > 2)
858 {
859 MHParseNode *pNewTimer = p->GetArgN(2);
860 m_timerValue.Initialise(pNewTimer->GetSeqN(0), engine);
861
862 if (pNewTimer->GetSeqCount() > 1)
863 {
864 m_timerType = ST_TimerAbsolute; // May be absolute - depends on the value.
865 m_absFlag.Initialise(pNewTimer->GetSeqN(1), engine);
866 }
867 else
868 {
869 m_timerType = ST_TimerRelative;
870 }
871 }
872}
873
874void MHSetTimer::PrintArgs(FILE *fd, int /*nTabs*/) const
875{
876 m_timerId.PrintMe(fd, 0);
877
878 if (m_timerType != ST_NoNewTimer)
879 {
880 fprintf(fd, "( ");
881 m_timerValue.PrintMe(fd, 0);
882
883 if (m_timerType == ST_TimerAbsolute)
884 {
885 m_absFlag.PrintMe(fd, 0);
886 }
887
888 fprintf(fd, ") ");
889 }
890}
891
893{
894 int nTimerId = m_timerId.GetValue(engine);
895 bool fAbsolute = false; // Defaults to relative time.
896 int newTime = -1;
897
898 switch (m_timerType)
899 {
900 case ST_NoNewTimer:
901 fAbsolute = true;
902 newTime = -1;
903 break; // We treat an absolute time of -1 as "cancel"
904 case ST_TimerAbsolute:
905 fAbsolute = m_absFlag.GetValue(engine);
906 [[fallthrough]];
907 case ST_TimerRelative:
908 newTime = m_timerValue.GetValue(engine);
909 }
910
911 Target(engine)->SetTimer(nTimerId, fAbsolute, newTime, engine);
912}
913
915{
916 MHElemAction::Initialise(p, engine); // Target
917 m_succeeded.Initialise(p->GetArgN(1), engine);
918 MHParseNode *pVarSeq = p->GetArgN(2);
919
920 for (int i = 0; i < pVarSeq->GetSeqCount(); i++)
921 {
922 auto *pVar = new MHObjectRef;
923 m_variables.Append(pVar);
924 pVar->Initialise(pVarSeq->GetSeqN(i), engine);
925 }
926
927 m_fileName.Initialise(p->GetArgN(3), engine);
928}
929
930void MHPersistent::PrintArgs(FILE *fd, int nTabs) const
931{
932 m_succeeded.PrintMe(fd, nTabs);
933 fprintf(fd, " ( ");
934
935 for (int i = 0; i < m_variables.Size(); i++)
936 {
937 m_variables.GetAt(i)->PrintMe(fd, 0);
938 }
939
940 fprintf(fd, " ) ");
941 m_fileName.PrintMe(fd, nTabs);
942}
943
945{
946 MHObjectRef target;
947 m_target.GetValue(target, engine); // Get the target - this should always be the application
948 MHOctetString fileName;
949 m_fileName.GetValue(fileName, engine);
950 bool fResult = engine->LoadStorePersistent(m_fIsLoad, fileName, m_variables);
951 engine->FindObject(m_succeeded)->SetVariableValue(fResult);
952}
953
955 : MHElemAction(":TransitionTo")
956 {}
957
959{
960 MHElemAction::Initialise(p, engine); // Target
961 // The next one may be present but NULL in binary.
962 if (p->GetArgCount() > 1)
963 {
964 MHParseNode *pCtag = p->GetArgN(1);
965
966 if (pCtag->m_nNodeType == MHParseNode::PNInt)
967 {
968 m_fIsTagged = true;
969 m_nConnectionTag = pCtag->GetIntValue();
970 }
971 }
972
973 if (p->GetArgCount() > 2)
974 {
975 MHParseNode *pTrEff = p->GetArgN(2);
977 }
978}
979
980void MHTransitionTo::PrintArgs(FILE *fd, int /*nTabs*/) const
981{
982 if (m_fIsTagged)
983 {
984 fprintf(fd, " %d ", m_nConnectionTag);
985 }
986 else if (m_nTransitionEffect >= 0)
987 {
988 fprintf(fd, " NULL ");
989 }
990
991 if (m_nTransitionEffect >= 0)
992 {
993 fprintf(fd, " %d", m_nTransitionEffect);
994 }
995}
996
997// Do the action - Transition to a new scene.
999{
1000 MHObjectRef target;
1001 m_target.GetValue(target, engine); // Get the target
1002 engine->TransitionToScene(target);
1003}
1004
1006{
1007 MHObjectRef target;
1008 m_target.GetValue(target, engine);
1009 engine->Launch(target);
1010}
1012{
1013 engine->Quit();
1014}
1016{
1017 MHObjectRef target;
1018 m_target.GetValue(target, engine);
1019 engine->Spawn(target);
1020}
1022{
1023 engine->LockScreen();
1024}
1026{
1027 engine->UnlockScreen();
1028}
1029
1031{
1032 MHElemAction::Initialise(p, engine);
1033 m_feature.Initialise(p->GetArgN(1), engine);
1034 m_answer.Initialise(p->GetArgN(2), engine);
1035}
1036
1038{
1039 // Ignore the target which isn't used.
1041 m_feature.GetValue(feature, engine);
1043}
@ C_OBJECT_REF_VARIABLE
Definition: ASN1Codes.h:54
@ C_BITMAP
Definition: ASN1Codes.h:58
@ C_HYPER_TEXT
Definition: ASN1Codes.h:67
@ C_ITEMS
Definition: ASN1Codes.h:44
@ C_ENTRY_FIELD
Definition: ASN1Codes.h:66
@ C_OCTET_STRING_VARIABLE
Definition: ASN1Codes.h:53
@ C_FONT_ATTRIBUTES
Definition: ASN1Codes.h:79
@ C_BACKGROUND_COLOUR
Definition: ASN1Codes.h:75
@ C_TEXT_CONTENT_HOOK
Definition: ASN1Codes.h:76
@ C_STREAM_CONTENT_HOOK
Definition: ASN1Codes.h:81
@ C_PUSH_BUTTON
Definition: ASN1Codes.h:64
@ C_DYNAMIC_LINE_ART
Definition: ASN1Codes.h:60
@ C_INTEGER_VARIABLE
Definition: ASN1Codes.h:52
@ C_IP_CONTENT_HOOK
Definition: ASN1Codes.h:80
@ C_HOTSPOT
Definition: ASN1Codes.h:62
@ C_SLIDER_REF_COLOUR
Definition: ASN1Codes.h:86
@ C_DEFAULT_ATTRIBUTES
Definition: ASN1Codes.h:73
@ C_BITMAP_CONTENT_HOOK
Definition: ASN1Codes.h:82
@ C_RESIDENT_PROGRAM
Definition: ASN1Codes.h:45
@ C_SCENE_COORDINATE_SYSTEM
Definition: ASN1Codes.h:88
@ C_INTERCHANGED_PROGRAM
Definition: ASN1Codes.h:47
@ C_CONTENT_REF_VARIABLE
Definition: ASN1Codes.h:55
@ C_STREAM
Definition: ASN1Codes.h:57
@ C_ON_CLOSE_DOWN
Definition: ASN1Codes.h:42
@ C_LINK
Definition: ASN1Codes.h:56
@ C_PALETTE
Definition: ASN1Codes.h:48
@ C_ASPECT_RATIO
Definition: ASN1Codes.h:89
@ C_FONT2
Definition: ASN1Codes.h:78
@ C_TEXT_COLOUR
Definition: ASN1Codes.h:77
@ C_MOVING_CURSOR
Definition: ASN1Codes.h:90
@ C_BUTTON_REF_COLOUR
Definition: ASN1Codes.h:84
@ C_SLIDER
Definition: ASN1Codes.h:68
@ C_CHARACTER_SET
Definition: ASN1Codes.h:74
@ C_INPUT_EVENT_REGISTER
Definition: ASN1Codes.h:87
@ C_BOOLEAN_VARIABLE
Definition: ASN1Codes.h:51
@ C_LINE_ART_CONTENT_HOOK
Definition: ASN1Codes.h:83
@ C_SWITCH_BUTTON
Definition: ASN1Codes.h:63
@ C_TEXT
Definition: ASN1Codes.h:65
@ C_TOKEN_GROUP
Definition: ASN1Codes.h:69
@ C_ON_START_UP
Definition: ASN1Codes.h:41
@ C_ON_SPAWN_CLOSE_DOWN
Definition: ASN1Codes.h:71
@ C_CURSOR_SHAPE
Definition: ASN1Codes.h:50
@ C_REMOTE_PROGRAM
Definition: ASN1Codes.h:46
@ C_LINE_ART
Definition: ASN1Codes.h:59
@ C_ORIGINAL_GC_PRIORITY
Definition: ASN1Codes.h:43
@ C_ON_RESTART
Definition: ASN1Codes.h:72
@ C_FONT
Definition: ASN1Codes.h:49
@ C_LIST_GROUP
Definition: ASN1Codes.h:70
@ C_HIGHLIGHT_REF_COLOUR
Definition: ASN1Codes.h:85
@ C_RECTANGLE
Definition: ASN1Codes.h:61
FILE * gMHLogStream
Definition: Engine.cpp:1525
#define MHERROR(__text)
Definition: Logging.h:42
#define MHLOG(__level, __text)
Definition: Logging.h:36
void PrintTabs(FILE *fd, int n)
Definition: ParseNode.cpp:34
EventType
Definition: Root.h:34
@ EventIsRunning
Definition: Root.h:34
@ EventTimerFired
Definition: Root.h:35
static const std::array< featureStruct, 7 > feature
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Actions.cpp:456
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Actions.cpp:67
MHColour m_buttonRefColour
Definition: Groups.h:134
MHColour m_textColour
Definition: Groups.h:134
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:438
int m_nLineArtCHook
Definition: Groups.h:139
MHColour m_highlightRefColour
Definition: Groups.h:134
int m_nBitmapCHook
Definition: Groups.h:138
MHColour m_sliderRefColour
Definition: Groups.h:134
int m_nCharSet
Definition: Groups.h:133
int m_nTextCHook
Definition: Groups.h:135
~MHApplication() override
Definition: Groups.cpp:433
int FindOnStack(const MHRoot *pVis)
Definition: Groups.cpp:707
void Activation(MHEngine *engine) override
Definition: Groups.cpp:689
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:569
MHSequence< MHVisible * > m_displayStack
Definition: Groups.h:148
MHOctetString m_fontAttrs
Definition: Groups.h:141
MHActionSequence m_onRestart
Definition: Groups.h:131
MHScene * m_pCurrentScene
Definition: Groups.h:151
int m_nIPCHook
Definition: Groups.h:136
MHActionSequence m_onSpawnCloseDown
Definition: Groups.h:131
MHFontBody m_font
Definition: Groups.h:140
MHColour m_bgColour
Definition: Groups.h:134
int m_nStrCHook
Definition: Groups.h:137
bool m_fRestarting
Definition: Groups.h:152
bool IsSet() const
Definition: BaseClasses.h:144
void Initialise(MHParseNode *p, MHEngine *engine)
void PrintMe(FILE *fd, int nTabs) const
MHRoot * Target(MHEngine *engine)
Definition: BaseActions.cpp:46
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: BaseActions.cpp:31
MHGenericObjectRef m_target
Definition: BaseActions.h:46
void Quit()
Definition: Engine.cpp:367
void TransitionToScene(const MHObjectRef &target)
Definition: Engine.cpp:409
void LockScreen()
Definition: Engine.h:110
MHRoot * FindObject(const MHObjectRef &oRef, bool failOnNotFound=true)
Definition: Engine.cpp:574
bool Launch(const MHObjectRef &target, bool fIsSpawn=false)
Definition: Engine.cpp:263
bool LoadStorePersistent(bool fIsLoad, const MHOctetString &fileName, const MHSequence< MHObjectRef * > &variables)
Definition: Engine.cpp:1152
bool GetEngineSupport(const MHOctetString &feature)
Definition: Engine.cpp:1234
void SetInputRegister(int nReg)
Definition: Engine.cpp:517
void UnlockScreen()
Definition: Engine.cpp:932
void EventTriggered(MHRoot *pSource, enum EventType ev)
Definition: Engine.h:94
MHOctetString & GetGroupId()
Definition: Engine.h:153
void RunActions()
Definition: Engine.cpp:614
void AddActions(const MHActionSequence &actions)
Definition: Engine.cpp:729
void Spawn(const MHObjectRef &target)
Definition: Engine.h:85
void PrintMe(FILE *fd, int nTabs) const
bool IsSet() const
Definition: BaseClasses.h:315
void Initialise(MHParseNode *p, MHEngine *engine)
void PrintMe(FILE *fd, int nTabs) const
void Initialise(MHParseNode *p, MHEngine *engine)
bool GetValue(MHEngine *engine) const
void Initialise(MHParseNode *p, MHEngine *engine)
int GetValue(MHEngine *engine) const
void PrintMe(FILE *fd, int nTabs) const
void Initialise(MHParseNode *p, MHEngine *engine)
void PrintMe(FILE *fd, int nTabs) const
void GetValue(MHObjectRef &ref, MHEngine *engine) const
void PrintMe(FILE *fd, int nTabs) const
void Initialise(MHParseNode *p, MHEngine *engine)
void GetValue(MHOctetString &str, MHEngine *engine) const
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1037
MHObjectRef m_answer
Definition: Groups.h:270
MHGenericOctetString m_feature
Definition: Groups.h:269
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:1030
void MakeClone(MHRoot *pTarget, MHRoot *pRef, MHEngine *engine) override
Definition: Groups.cpp:422
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:217
void Preparation(MHEngine *engine) override
Definition: Groups.cpp:258
MHActionSequence m_startUp
Definition: Groups.h:70
MHRoot * FindByObjectNo(int n) override
Definition: Groups.cpp:330
MHActionSequence m_closeDown
Definition: Groups.h:70
void SetTimer(int nTimerId, bool fAbsolute, int nMilliSecs, MHEngine *engine) override
Definition: Groups.cpp:351
void Destruction(MHEngine *engine) override
Definition: Groups.cpp:319
MHOwnPtrSequence< MHIngredient > m_items
Definition: Groups.h:71
std::chrono::milliseconds CheckTimers(MHEngine *engine)
Definition: Groups.cpp:387
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:51
void Deactivation(MHEngine *engine) override
Definition: Groups.cpp:305
QElapsedTimer m_runTime
Definition: Groups.h:78
QList< MHTimer * > m_timers
Definition: Groups.h:79
void Activation(MHEngine *engine) override
Definition: Groups.cpp:275
int m_nLastId
Definition: Groups.h:83
int m_nOrigGCPriority
Definition: Groups.h:69
~MHGroup() override
Definition: Groups.cpp:43
void Destruction(MHEngine *engine) override
void Preparation(MHEngine *engine) override
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Ingredients.cpp:50
virtual bool InitiallyAvailable()
Definition: Ingredients.h:43
void PrintMe(FILE *fd, int nTabs) const override
virtual bool InitiallyActive()
Definition: Ingredients.h:42
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1005
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1021
MHOctetString m_groupId
Definition: BaseClasses.h:170
void PrintMe(FILE *fd, int nTabs) const
void Initialise(MHParseNode *p, MHEngine *engine)
void Copy(const MHOctetString &str)
int Size() const
Definition: BaseClasses.h:120
void PrintMe(FILE *fd, int nTabs) const
enum MHParameter::ParamTypes P_Null
void Initialise(MHParseNode *p, MHEngine *engine)
void PrintMe(FILE *fd, int nTabs) const
MHParseNode * GetSeqN(int n)
Definition: ParseNode.cpp:152
MHParseNode * GetArgN(int n)
Definition: ParseNode.cpp:78
static void Failure(const char *p)
Definition: ParseNode.cpp:43
void GetStringValue(MHOctetString &str)
Definition: ParseNode.cpp:203
int GetArgCount()
Definition: ParseNode.cpp:60
int GetTagNo()
Definition: ParseNode.cpp:49
bool GetBoolValue()
Definition: ParseNode.cpp:192
int GetSeqCount()
Definition: ParseNode.cpp:141
MHParseNode * GetNamedArg(int nTag)
Definition: ParseNode.cpp:110
enum NodeType m_nNodeType
Definition: ParseNode.h:46
int GetIntValue()
Definition: ParseNode.cpp:170
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:930
MHObjectRef m_succeeded
Definition: Groups.h:225
void Perform(MHEngine *engine) override
Definition: Groups.cpp:944
bool m_fIsLoad
Definition: Groups.h:224
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:914
MHGenericOctetString m_fileName
Definition: Groups.h:227
MHOwnPtrSequence< MHObjectRef > m_variables
Definition: Groups.h:226
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1011
Definition: Root.h:45
virtual void Initialise(MHParseNode *p, MHEngine *engine)
Definition: Root.cpp:30
virtual void Activation(MHEngine *engine)
Definition: Root.cpp:70
virtual void Destruction(MHEngine *engine)
Definition: Root.cpp:98
MHObjectRef m_ObjectReference
Definition: Root.h:248
virtual void Deactivation(MHEngine *engine)
Definition: Root.cpp:86
virtual void SetTimer(int, bool, int, MHEngine *)
Definition: Root.h:80
virtual MHIngredient * Clone(MHEngine *)
Definition: Root.h:97
virtual void Preparation(MHEngine *engine)
Definition: Root.cpp:53
bool m_fRunning
Definition: Root.h:253
virtual void PrintMe(FILE *fd, int nTabs) const
Definition: Root.cpp:38
virtual MHRoot * FindByObjectNo(int n)
Definition: Root.cpp:116
virtual void SetVariableValue(const MHUnion &)
Definition: Root.h:109
int m_nAspectRatioH
Definition: Groups.h:109
bool m_fMovingCursor
Definition: Groups.h:110
void PrintMe(FILE *fd, int nTabs) const override
Definition: Groups.cpp:761
int m_nAspectRatioW
Definition: Groups.h:108
void Activation(MHEngine *engine) override
Definition: Groups.cpp:786
int m_nSceneCoordY
Definition: Groups.h:104
int m_nSceneCoordX
Definition: Groups.h:103
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:720
void SetInputRegister(int nReg, MHEngine *engine) override
Definition: Groups.cpp:798
int m_nEventReg
Definition: Groups.h:102
MHGenericObjectRef m_eventSource
Definition: Groups.h:183
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:818
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:805
MHParameter m_eventData
Definition: Groups.h:185
void Perform(MHEngine *engine) override
Definition: Groups.cpp:831
int Size() const
Definition: BaseClasses.h:47
void Append(BASE b)
Definition: BaseClasses.h:64
BASE GetAt(int i) const
Definition: BaseClasses.h:49
MHGenericInteger m_timerValue
Definition: Groups.h:204
MHGenericBoolean m_absFlag
Definition: Groups.h:205
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:852
MHGenericInteger m_timerId
Definition: Groups.h:196
void Perform(MHEngine *engine) override
Definition: Groups.cpp:892
@ ST_TimerRelative
Definition: Groups.h:202
@ ST_TimerAbsolute
Definition: Groups.h:201
enum MHSetTimer::@9 ST_NoNewTimer
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:874
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1015
Definition: Text.h:38
Definition: Groups.h:40
QTime m_Time
Definition: Groups.h:43
int m_nTimerId
Definition: Groups.h:42
void Perform(MHEngine *engine) override
Definition: Groups.cpp:998
int m_nConnectionTag
Definition: Groups.h:241
void Initialise(MHParseNode *p, MHEngine *engine) override
Definition: Groups.cpp:958
bool m_fIsTagged
Definition: Groups.h:240
void PrintArgs(FILE *fd, int nTabs) const override
Definition: Groups.cpp:980
int m_nTransitionEffect
Definition: Groups.h:242
void GetValueFrom(const MHParameter &value, MHEngine *engine)
void Perform(MHEngine *engine) override
Definition: Groups.cpp:1025
@ MHLogError
Definition: freemheg.h:77
@ MHLogWarning
Definition: freemheg.h:78
static guint32 * tmp
Definition: goom_core.cpp:26
int FILE
Definition: mythburn.py:138