|
MythTV
0.26-pre
|
00001 /* Groups.cpp 00002 00003 Copyright (C) David C. J. Matthews 2004 dm at prolingua.co.uk 00004 00005 This program is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU General Public License 00007 as published by the Free Software Foundation; either version 2 00008 of the License, or (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00019 00020 */ 00021 00022 #include "Root.h" 00023 #include "Groups.h" 00024 #include "ASN1Codes.h" 00025 #include "ParseNode.h" 00026 #include "Ingredients.h" 00027 #include "Programs.h" 00028 #include "Variables.h" 00029 #include "Presentable.h" 00030 #include "Visible.h" 00031 #include "Engine.h" 00032 #include "Text.h" 00033 #include "Bitmap.h" 00034 #include "Stream.h" 00035 #include "DynamicLineArt.h" 00036 #include "Link.h" 00037 #include "TokenGroup.h" 00038 #include "Logging.h" 00039 00040 MHGroup::MHGroup() 00041 { 00042 m_nOrigGCPriority = 127; // Default. 00043 m_fIsApp = false; 00044 m_nLastId = 0; 00045 } 00046 00047 MHGroup::~MHGroup() 00048 { 00049 while (!m_Timers.isEmpty()) 00050 { 00051 delete m_Timers.takeFirst(); 00052 } 00053 } 00054 00055 void MHGroup::Initialise(MHParseNode *p, MHEngine *engine) 00056 { 00057 engine->GetGroupId().Copy(""); // Set to empty before we start (just in case). 00058 MHRoot::Initialise(p, engine); 00059 00060 // Must be an external reference with an object number of zero. 00061 if (m_ObjectReference.m_nObjectNo != 0 || m_ObjectReference.m_GroupId.Size() == 0) 00062 { 00063 MHERROR("Object reference for a group object must be zero and external"); 00064 } 00065 00066 // Set the group id for the rest of the group to this. 00067 engine->GetGroupId().Copy(m_ObjectReference.m_GroupId); 00068 // Some of the information is irrelevant. 00069 // MHParseNode *pStdId = p->GetNamedArg(C_STANDARD_IDENTIFIER); 00070 // MHParseNode *pStdVersion = p->GetNamedArg(C_STANDARD_VERSION); 00071 // MHParseNode *pObjectInfo = p->GetNamedArg(C_OBJECT_INFORMATION); 00072 00073 MHParseNode *pOnStartUp = p->GetNamedArg(C_ON_START_UP); 00074 00075 if (pOnStartUp) 00076 { 00077 m_StartUp.Initialise(pOnStartUp, engine); 00078 } 00079 00080 MHParseNode *pOnCloseDown = p->GetNamedArg(C_ON_CLOSE_DOWN); 00081 00082 if (pOnCloseDown) 00083 { 00084 m_CloseDown.Initialise(pOnCloseDown, engine); 00085 } 00086 00087 MHParseNode *pOriginalGCPrio = p->GetNamedArg(C_ORIGINAL_GC_PRIORITY); 00088 00089 if (pOriginalGCPrio) 00090 { 00091 m_nOrigGCPriority = pOriginalGCPrio->GetArgN(0)->GetIntValue(); 00092 } 00093 00094 // Ignore the other stuff at the moment. 00095 MHParseNode *pItems = p->GetNamedArg(C_ITEMS); 00096 00097 if (pItems == NULL) 00098 { 00099 p->Failure("Missing :Items block"); 00100 return; 00101 } 00102 00103 for (int i = 0; i < pItems->GetArgCount(); i++) 00104 { 00105 MHParseNode *pItem = pItems->GetArgN(i); 00106 MHIngredient *pIngredient = NULL; 00107 00108 try 00109 { 00110 // Generate the particular kind of ingredient. 00111 switch (pItem->GetTagNo()) 00112 { 00113 case C_RESIDENT_PROGRAM: 00114 pIngredient = new MHResidentProgram; 00115 break; 00116 case C_REMOTE_PROGRAM: 00117 pIngredient = new MHRemoteProgram; 00118 break; 00119 case C_INTERCHANGED_PROGRAM: 00120 pIngredient = new MHInterChgProgram; 00121 break; 00122 case C_PALETTE: 00123 pIngredient = new MHPalette; 00124 break; 00125 case C_FONT: 00126 pIngredient = new MHFont; 00127 break; 00128 case C_CURSOR_SHAPE: 00129 pIngredient = new MHCursorShape; 00130 break; 00131 case C_BOOLEAN_VARIABLE: 00132 pIngredient = new MHBooleanVar; 00133 break; 00134 case C_INTEGER_VARIABLE: 00135 pIngredient = new MHIntegerVar; 00136 break; 00137 case C_OCTET_STRING_VARIABLE: 00138 pIngredient = new MHOctetStrVar; 00139 break; 00140 case C_OBJECT_REF_VARIABLE: 00141 pIngredient = new MHObjectRefVar; 00142 break; 00143 case C_CONTENT_REF_VARIABLE: 00144 pIngredient = new MHContentRefVar; 00145 break; 00146 case C_LINK: 00147 pIngredient = new MHLink; 00148 break; 00149 case C_STREAM: 00150 pIngredient = new MHStream; 00151 break; 00152 case C_BITMAP: 00153 pIngredient = new MHBitmap; 00154 break; 00155 case C_LINE_ART: 00156 pIngredient = new MHLineArt; 00157 break; 00158 case C_DYNAMIC_LINE_ART: 00159 pIngredient = new MHDynamicLineArt; 00160 break; 00161 case C_RECTANGLE: 00162 pIngredient = new MHRectangle; 00163 break; 00164 case C_HOTSPOT: 00165 pIngredient = new MHHotSpot; 00166 break; 00167 case C_SWITCH_BUTTON: 00168 pIngredient = new MHSwitchButton; 00169 break; 00170 case C_PUSH_BUTTON: 00171 pIngredient = new MHPushButton; 00172 break; 00173 case C_TEXT: 00174 pIngredient = new MHText; 00175 break; 00176 case C_ENTRY_FIELD: 00177 pIngredient = new MHEntryField; 00178 break; 00179 case C_HYPER_TEXT: 00180 pIngredient = new MHHyperText; 00181 break; 00182 case C_SLIDER: 00183 pIngredient = new MHSlider; 00184 break; 00185 case C_TOKEN_GROUP: 00186 pIngredient = new MHTokenGroup; 00187 break; 00188 case C_LIST_GROUP: 00189 pIngredient = new MHListGroup; 00190 break; 00191 default: 00192 MHLOG(MHLogWarning, QString("Unknown ingredient %1").arg(pItem->GetTagNo())); 00193 // Future proofing: ignore any ingredients that we don't know about. 00194 // Obviously these can only arise in the binary coding. 00195 } 00196 00197 if (pIngredient) 00198 { 00199 // Initialise it from its argments. 00200 pIngredient->Initialise(pItem, engine); 00201 00202 // Remember the highest numbered ingredient 00203 if (pIngredient->m_ObjectReference.m_nObjectNo > m_nLastId) 00204 { 00205 m_nLastId = pIngredient->m_ObjectReference.m_nObjectNo; 00206 } 00207 00208 // Add it to the ingedients of this group. 00209 m_Items.Append(pIngredient); 00210 } 00211 } 00212 catch (...) 00213 { 00214 delete(pIngredient); 00215 throw; 00216 } 00217 } 00218 } 00219 00220 void MHGroup::PrintMe(FILE *fd, int nTabs) const 00221 { 00222 MHRoot::PrintMe(fd, nTabs); 00223 00224 if (m_StartUp.Size() != 0) 00225 { 00226 PrintTabs(fd, nTabs + 1); 00227 fprintf(fd, ":OnStartUp (\n"); 00228 m_StartUp.PrintMe(fd, nTabs + 2); 00229 PrintTabs(fd, nTabs + 2); 00230 fprintf(fd, ")\n"); 00231 } 00232 00233 if (m_CloseDown.Size() != 0) 00234 { 00235 PrintTabs(fd, nTabs + 1); 00236 fprintf(fd, ":OnCloseDown (\n"); 00237 m_CloseDown.PrintMe(fd, nTabs + 2); 00238 PrintTabs(fd, nTabs + 2); 00239 fprintf(fd, ")\n"); 00240 } 00241 00242 if (m_nOrigGCPriority != 127) 00243 { 00244 PrintTabs(fd, nTabs + 1); 00245 fprintf(fd, ":OrigGCPriority %d\n", m_nOrigGCPriority); 00246 } 00247 00248 PrintTabs(fd, nTabs + 1); 00249 fprintf(fd, ":Items ( \n"); 00250 00251 for (int i = 0; i < m_Items.Size(); i++) 00252 { 00253 m_Items.GetAt(i)->PrintMe(fd, nTabs + 2); 00254 } 00255 00256 PrintTabs(fd, nTabs + 1); 00257 fprintf(fd, ")\n"); 00258 } 00259 00260 // Preparation - sets up the run-time representation. Sets m_fAvailable and generates IsAvailable event. 00261 void MHGroup::Preparation(MHEngine *engine) 00262 { 00263 // Prepare the ingredients first if they are initially active or are initially available programs. 00264 for (int i = 0; i < m_Items.Size(); i++) 00265 { 00266 MHIngredient *pIngredient = m_Items.GetAt(i); 00267 00268 if (pIngredient->InitiallyActive() || pIngredient->InitiallyAvailable()) 00269 { 00270 pIngredient->Preparation(engine); 00271 } 00272 } 00273 00274 MHRoot::Preparation(engine); // Prepare the root object and send the IsAvailable event. 00275 } 00276 00277 // Activation - starts running the object. Sets m_fRunning and generates IsRunning event. 00278 void MHGroup::Activation(MHEngine *engine) 00279 { 00280 if (m_fRunning) 00281 { 00282 return; 00283 } 00284 00285 MHRoot::Activation(engine); 00286 // Run any start-up actions. 00287 engine->AddActions(m_StartUp); 00288 engine->RunActions(); 00289 00290 // Activate the ingredients in order. 00291 for (int i = 0; i < m_Items.Size(); i++) 00292 { 00293 MHIngredient *pIngredient = m_Items.GetAt(i); 00294 00295 if (pIngredient->InitiallyActive()) 00296 { 00297 pIngredient->Activation(engine); 00298 } 00299 } 00300 00301 m_fRunning = true; 00302 // Record the time here. This is the basis for absolute times. 00303 m_StartTime.start(); 00304 // Don't generate IsRunning here - that's done by the sub-classes. 00305 } 00306 00307 // Deactivation - stops running the object. Clears m_fRunning 00308 void MHGroup::Deactivation(MHEngine *engine) 00309 { 00310 if (! m_fRunning) 00311 { 00312 return; 00313 } 00314 00315 // Run any close-down actions. 00316 engine->AddActions(m_CloseDown); 00317 engine->RunActions(); 00318 MHRoot::Deactivation(engine); 00319 } 00320 00321 // Destruction - deletes the run-time representation. Clears m_fAvailable. 00322 void MHGroup::Destruction(MHEngine *engine) 00323 { 00324 for (int i = m_Items.Size(); i > 0; i--) 00325 { 00326 m_Items.GetAt(i - 1)->Destruction(engine); 00327 } 00328 00329 MHRoot::Destruction(engine); 00330 } 00331 00332 // Return an object if its object ID matches (or if it's a stream, if it has a matching component). 00333 MHRoot *MHGroup::FindByObjectNo(int n) 00334 { 00335 if (n == m_ObjectReference.m_nObjectNo) 00336 { 00337 return this; 00338 } 00339 00340 for (int i = m_Items.Size(); i > 0; i--) 00341 { 00342 MHRoot *pResult = m_Items.GetAt(i - 1)->FindByObjectNo(n); 00343 00344 if (pResult) 00345 { 00346 return pResult; 00347 } 00348 } 00349 00350 return NULL; 00351 } 00352 00353 // Set up a timer or cancel a timer. 00354 void MHGroup::SetTimer(int nTimerId, bool fAbsolute, int nMilliSecs, MHEngine *) 00355 { 00356 // First remove any existing timer with the same Id. 00357 for (int i = 0; i < m_Timers.size(); i++) 00358 { 00359 MHTimer *pTimer = m_Timers.at(i); 00360 00361 if (pTimer->m_nTimerId == nTimerId) 00362 { 00363 delete m_Timers.takeAt(i); 00364 break; 00365 } 00366 } 00367 00368 // If the time has passed we don't set up a timer. 00369 QTime currentTime; 00370 currentTime.start(); // Set current time 00371 00372 if (nMilliSecs < 0 || (fAbsolute && m_StartTime.addMSecs(nMilliSecs) < currentTime)) 00373 { 00374 return; 00375 } 00376 00377 MHTimer *pTimer = new MHTimer; 00378 m_Timers.append(pTimer); 00379 pTimer->m_nTimerId = nTimerId; 00380 00381 if (fAbsolute) 00382 { 00383 pTimer->m_Time = m_StartTime.addMSecs(nMilliSecs); 00384 } 00385 else 00386 { 00387 pTimer->m_Time = currentTime.addMSecs(nMilliSecs); 00388 } 00389 } 00390 00391 // Fire any timers that have passed. 00392 int MHGroup::CheckTimers(MHEngine *engine) 00393 { 00394 QTime currentTime = QTime::currentTime(); // Get current time 00395 QList<MHTimer *>::iterator it = m_Timers.begin(); 00396 MHTimer *pTimer; 00397 int nMSecs = 0; 00398 00399 while (it != m_Timers.end()) 00400 { 00401 pTimer = *it; 00402 00403 if (pTimer->m_Time <= currentTime) // Use <= rather than < here so we fire timers with zero time immediately. 00404 { 00405 // If the time has passed trigger the event and remove the timer from the queue. 00406 engine->EventTriggered(this, EventTimerFired, pTimer->m_nTimerId); 00407 delete pTimer; 00408 it = m_Timers.erase(it); 00409 } 00410 else 00411 { 00412 // This has not yet expired. Set "nMSecs" to the earliest time we have. 00413 int nMSecsToGo = currentTime.msecsTo(pTimer->m_Time); 00414 00415 if (nMSecs == 0 || nMSecsToGo < nMSecs) 00416 { 00417 nMSecs = nMSecsToGo; 00418 } 00419 00420 ++it; 00421 } 00422 } 00423 00424 return nMSecs; 00425 } 00426 00427 // Create a clone of the target and add it to the ingredients. 00428 void MHGroup::MakeClone(MHRoot *pTarget, MHRoot *pRef, MHEngine *engine) 00429 { 00430 MHIngredient *pClone = pTarget->Clone(engine); // Clone it. 00431 pClone->m_ObjectReference.m_GroupId.Copy(m_ObjectReference.m_GroupId); // Group id is the same as this. 00432 pClone->m_ObjectReference.m_nObjectNo = ++m_nLastId; // Create a new object id. 00433 m_Items.Append(pClone); 00434 // Set the object reference result to the newly constructed ref. 00435 pRef->SetVariableValue(pClone->m_ObjectReference); 00436 pClone->Preparation(engine); // Prepare the clone. 00437 } 00438 00439 MHApplication::MHApplication() 00440 { 00441 m_fIsApp = true; 00442 m_nCharSet = 0; 00443 m_nTextCHook = 0; 00444 m_nIPCHook = 0; 00445 m_nStrCHook = 0; 00446 m_nBitmapCHook = 0; 00447 m_nLineArtCHook = 0; 00448 m_tuneinfo = 0; 00449 00450 m_pCurrentScene = NULL; 00451 m_nLockCount = 0; 00452 m_fRestarting = false; 00453 } 00454 00455 MHApplication::~MHApplication() 00456 { 00457 delete(m_pCurrentScene); 00458 } 00459 00460 void MHApplication::Initialise(MHParseNode *p, MHEngine *engine) 00461 { 00462 MHGroup::Initialise(p, engine); 00463 // OnSpawnCloseDown 00464 MHParseNode *pOnSpawn = p->GetNamedArg(C_ON_SPAWN_CLOSE_DOWN); 00465 00466 if (pOnSpawn) 00467 { 00468 m_OnSpawnCloseDown.Initialise(pOnSpawn, engine); 00469 } 00470 00471 // OnRestart 00472 MHParseNode *pOnRestart = p->GetNamedArg(C_ON_RESTART); 00473 00474 if (pOnRestart) 00475 { 00476 m_OnRestart.Initialise(pOnRestart, engine); 00477 } 00478 00479 // Default attributes. These are encoded in a group in binary. 00480 MHParseNode *pDefattrs = p->GetNamedArg(C_DEFAULT_ATTRIBUTES); 00481 00482 // but in the text form they're encoded in the Application block. 00483 if (pDefattrs == NULL) 00484 { 00485 pDefattrs = p; 00486 } 00487 00488 MHParseNode *pCharSet = pDefattrs->GetNamedArg(C_CHARACTER_SET); 00489 00490 if (pCharSet) 00491 { 00492 m_nCharSet = pCharSet->GetArgN(0)->GetIntValue(); 00493 } 00494 00495 // Colours 00496 MHParseNode *pBGColour = pDefattrs->GetNamedArg(C_BACKGROUND_COLOUR); 00497 00498 if (pBGColour) 00499 { 00500 m_BGColour.Initialise(pBGColour->GetArgN(0), engine); 00501 } 00502 00503 MHParseNode *pTextColour = pDefattrs->GetNamedArg(C_TEXT_COLOUR); 00504 00505 if (pTextColour) 00506 { 00507 m_TextColour.Initialise(pTextColour->GetArgN(0), engine); 00508 } 00509 00510 MHParseNode *pButtonRefColour = pDefattrs->GetNamedArg(C_BUTTON_REF_COLOUR); 00511 00512 if (pButtonRefColour) 00513 { 00514 m_ButtonRefColour.Initialise(pButtonRefColour->GetArgN(0), engine); 00515 } 00516 00517 MHParseNode *pHighlightRefColour = pDefattrs->GetNamedArg(C_HIGHLIGHT_REF_COLOUR); 00518 00519 if (pHighlightRefColour) 00520 { 00521 m_HighlightRefColour.Initialise(pHighlightRefColour->GetArgN(0), engine); 00522 } 00523 00524 MHParseNode *pSliderRefColour = pDefattrs->GetNamedArg(C_SLIDER_REF_COLOUR); 00525 00526 if (pSliderRefColour) 00527 { 00528 m_SliderRefColour.Initialise(pSliderRefColour->GetArgN(0), engine); 00529 } 00530 00531 // Content hooks 00532 MHParseNode *pTextCHook = pDefattrs->GetNamedArg(C_TEXT_CONTENT_HOOK); 00533 00534 if (pTextCHook) 00535 { 00536 m_nTextCHook = pTextCHook->GetArgN(0)->GetIntValue(); 00537 } 00538 00539 MHParseNode *pIPCHook = pDefattrs->GetNamedArg(C_IP_CONTENT_HOOK); 00540 00541 if (pIPCHook) 00542 { 00543 m_nIPCHook = pIPCHook->GetArgN(0)->GetIntValue(); 00544 } 00545 00546 MHParseNode *pStrCHook = pDefattrs->GetNamedArg(C_STREAM_CONTENT_HOOK); 00547 00548 if (pStrCHook) 00549 { 00550 m_nStrCHook = pStrCHook->GetArgN(0)->GetIntValue(); 00551 } 00552 00553 MHParseNode *pBitmapCHook = pDefattrs->GetNamedArg(C_BITMAP_CONTENT_HOOK); 00554 00555 if (pBitmapCHook) 00556 { 00557 m_nBitmapCHook = pBitmapCHook->GetArgN(0)->GetIntValue(); 00558 } 00559 00560 MHParseNode *pLineArtCHook = pDefattrs->GetNamedArg(C_LINE_ART_CONTENT_HOOK); 00561 00562 if (pLineArtCHook) 00563 { 00564 m_nLineArtCHook = pLineArtCHook->GetArgN(0)->GetIntValue(); 00565 } 00566 00567 // Font. This is a little tricky. There are two attributes both called Font. 00568 // In the binary notation the font here is encoded as 42 whereas the text form 00569 // finds the first occurrence of :Font in the table and returns 13. 00570 MHParseNode *pFont = pDefattrs->GetNamedArg(C_FONT2); 00571 00572 if (pFont == NULL) 00573 { 00574 pFont = pDefattrs->GetNamedArg(C_FONT); 00575 } 00576 00577 if (pFont) 00578 { 00579 m_Font.Initialise(pFont->GetArgN(0), engine); 00580 } 00581 00582 // Font attributes. 00583 MHParseNode *pFontAttrs = pDefattrs->GetNamedArg(C_FONT_ATTRIBUTES); 00584 00585 if (pFontAttrs) 00586 { 00587 pFontAttrs->GetArgN(0)->GetStringValue(m_FontAttrs); 00588 } 00589 } 00590 00591 void MHApplication::PrintMe(FILE *fd, int nTabs) const 00592 { 00593 PrintTabs(fd, nTabs); 00594 fprintf(fd, "{:Application "); 00595 MHGroup::PrintMe(fd, nTabs); 00596 00597 if (m_OnSpawnCloseDown.Size() != 0) 00598 { 00599 PrintTabs(fd, nTabs + 1); 00600 fprintf(fd, ":OnSpawnCloseDown"); 00601 m_OnSpawnCloseDown.PrintMe(fd, nTabs + 1); 00602 fprintf(fd, "\n"); 00603 } 00604 00605 if (m_OnRestart.Size() != 0) 00606 { 00607 PrintTabs(fd, nTabs + 1); 00608 fprintf(fd, ":OnRestart"); 00609 m_OnRestart.PrintMe(fd, nTabs + 1); 00610 fprintf(fd, "\n"); 00611 } 00612 00613 if (m_nCharSet > 0) 00614 { 00615 PrintTabs(fd, nTabs + 1); 00616 fprintf(fd, ":CharacterSet %d\n", m_nCharSet); 00617 } 00618 00619 if (m_BGColour.IsSet()) 00620 { 00621 PrintTabs(fd, nTabs + 1); 00622 fprintf(fd, ":BackgroundColour "); 00623 m_BGColour.PrintMe(fd, nTabs + 1); 00624 fprintf(fd, "\n"); 00625 } 00626 00627 if (m_nTextCHook > 0) 00628 { 00629 PrintTabs(fd, nTabs + 1); 00630 fprintf(fd, ":TextCHook %d\n", m_nTextCHook); 00631 } 00632 00633 if (m_TextColour.IsSet()) 00634 { 00635 PrintTabs(fd, nTabs + 1); 00636 fprintf(fd, ":TextColour"); 00637 m_TextColour.PrintMe(fd, nTabs + 1); 00638 fprintf(fd, "\n"); 00639 } 00640 00641 if (m_Font.IsSet()) 00642 { 00643 PrintTabs(fd, nTabs + 1); 00644 fprintf(fd, ":Font "); 00645 m_Font.PrintMe(fd, nTabs + 1); 00646 fprintf(fd, "\n"); 00647 } 00648 00649 if (m_FontAttrs.Size() > 0) 00650 { 00651 PrintTabs(fd, nTabs + 1); 00652 fprintf(fd, ":FontAttributes "); 00653 m_FontAttrs.PrintMe(fd, nTabs + 1); 00654 fprintf(fd, "\n"); 00655 } 00656 00657 if (m_nIPCHook > 0) 00658 { 00659 PrintTabs(fd, nTabs + 1); 00660 fprintf(fd, ":InterchgPrgCHook %d\n", m_nIPCHook); 00661 } 00662 00663 if (m_nStrCHook > 0) 00664 { 00665 PrintTabs(fd, nTabs + 1); 00666 fprintf(fd, ":StreamCHook %d\n", m_nStrCHook); 00667 } 00668 00669 if (m_nBitmapCHook > 0) 00670 { 00671 PrintTabs(fd, nTabs + 1); 00672 fprintf(fd, ":BitmapCHook %d\n", m_nBitmapCHook); 00673 } 00674 00675 if (m_nLineArtCHook > 0) 00676 { 00677 PrintTabs(fd, nTabs + 1); 00678 fprintf(fd, ":LineArtCHook %d\n", m_nLineArtCHook); 00679 } 00680 00681 if (m_ButtonRefColour.IsSet()) 00682 { 00683 PrintTabs(fd, nTabs + 1); 00684 fprintf(fd, ":ButtonRefColour "); 00685 m_ButtonRefColour.PrintMe(fd, nTabs + 1); 00686 fprintf(fd, "\n"); 00687 } 00688 00689 if (m_HighlightRefColour.IsSet()) 00690 { 00691 PrintTabs(fd, nTabs + 1); 00692 fprintf(fd, ":HighlightRefColour "); 00693 m_HighlightRefColour.PrintMe(fd, nTabs + 1); 00694 fprintf(fd, "\n"); 00695 } 00696 00697 if (m_SliderRefColour.IsSet()) 00698 { 00699 PrintTabs(fd, nTabs + 1); 00700 fprintf(fd, ":SliderRefColour "); 00701 m_SliderRefColour.PrintMe(fd, nTabs + 1); 00702 fprintf(fd, "\n"); 00703 } 00704 00705 fprintf(fd, "}\n"); 00706 } 00707 00708 // This is a bit messy. The MHEG corrigendum says that we need to process OnRestart actions 00709 // BEFORE generating IsRunning. That's important because TransitionTo etc are ignored during 00710 // OnRestart but allowed in events triggered by IsRunning. 00711 void MHApplication::Activation(MHEngine *engine) 00712 { 00713 if (m_fRunning) 00714 { 00715 return; 00716 } 00717 00718 MHGroup::Activation(engine); 00719 00720 if (m_fRestarting) // Set by Quit 00721 { 00722 engine->AddActions(m_OnRestart); 00723 engine->RunActions(); 00724 } 00725 00726 engine->EventTriggered(this, EventIsRunning); 00727 } 00728 00729 int MHApplication::FindOnStack(const MHRoot *pVis) // Returns the index on the stack or -1 if it's not there. 00730 { 00731 for (int i = 0; i < m_DisplayStack.Size(); i++) 00732 { 00733 if (m_DisplayStack.GetAt(i) == pVis) 00734 { 00735 return i; 00736 } 00737 } 00738 00739 return -1; // Not there 00740 } 00741 00742 MHScene::MHScene() 00743 { 00744 m_fIsApp = false; 00745 // TODO: In UK MHEG 1.06 the aspect ratio is optional and if not specified "the 00746 // scene has no aspect ratio". 00747 m_nAspectRatioW = 4; 00748 m_nAspectRatioH = 3; 00749 m_fMovingCursor = false; 00750 } 00751 00752 void MHScene::Initialise(MHParseNode *p, MHEngine *engine) 00753 { 00754 MHGroup::Initialise(p, engine); 00755 // Event register. 00756 MHParseNode *pInputEventReg = p->GetNamedArg(C_INPUT_EVENT_REGISTER); 00757 00758 if (pInputEventReg) 00759 { 00760 m_nEventReg = pInputEventReg->GetArgN(0)->GetIntValue(); 00761 } 00762 00763 // Co-ordinate system 00764 MHParseNode *pSceneCoords = p->GetNamedArg(C_SCENE_COORDINATE_SYSTEM); 00765 00766 if (pSceneCoords) 00767 { 00768 m_nSceneCoordX = pSceneCoords->GetArgN(0)->GetIntValue(); 00769 m_nSceneCoordY = pSceneCoords->GetArgN(1)->GetIntValue(); 00770 } 00771 00772 // Aspect ratio 00773 MHParseNode *pAspectRatio = p->GetNamedArg(C_ASPECT_RATIO); 00774 00775 if (pAspectRatio) 00776 { 00777 // Is the binary encoded as a sequence or a pair of arguments? 00778 m_nAspectRatioW = pAspectRatio->GetArgN(0)->GetIntValue(); 00779 m_nAspectRatioH = pAspectRatio->GetArgN(1)->GetIntValue(); 00780 } 00781 00782 // Moving cursor 00783 MHParseNode *pMovingCursor = p->GetNamedArg(C_MOVING_CURSOR); 00784 00785 if (pMovingCursor) 00786 { 00787 pMovingCursor->GetArgN(0)->GetBoolValue(); 00788 } 00789 00790 // Next scene sequence: this is just a hint and isn't implemented 00791 } 00792 00793 void MHScene::PrintMe(FILE *fd, int nTabs) const 00794 { 00795 PrintTabs(fd, nTabs); 00796 fprintf(fd, "{:Scene "); 00797 MHGroup::PrintMe(fd, nTabs); 00798 PrintTabs(fd, nTabs + 1); 00799 fprintf(fd, ":InputEventReg %d\n", m_nEventReg); 00800 PrintTabs(fd, nTabs + 1); 00801 fprintf(fd, ":SceneCS %d %d\n", m_nSceneCoordX, m_nSceneCoordY); 00802 00803 if (m_nAspectRatioW != 4 || m_nAspectRatioH != 3) 00804 { 00805 PrintTabs(fd, nTabs + 1); 00806 fprintf(fd, ":AspectRatio %d %d\n", m_nAspectRatioW, m_nAspectRatioH); 00807 } 00808 00809 if (m_fMovingCursor) 00810 { 00811 PrintTabs(fd, nTabs + 1); 00812 fprintf(fd, ":MovingCursor true\n"); 00813 } 00814 00815 fprintf(fd, "}\n"); 00816 } 00817 00818 void MHScene::Activation(MHEngine *engine) 00819 { 00820 if (m_fRunning) 00821 { 00822 return; 00823 } 00824 00825 MHGroup::Activation(engine); 00826 engine->EventTriggered(this, EventIsRunning); 00827 } 00828 00829 // Action added in UK MHEG profile. It doesn't define a new internal attribute for this. 00830 void MHScene::SetInputRegister(int nReg, MHEngine *engine) 00831 { 00832 m_nEventReg = nReg; 00833 engine->SetInputRegister(nReg); 00834 } 00835 00836 00837 void MHSendEvent::Initialise(MHParseNode *p, MHEngine *engine) 00838 { 00839 MHElemAction::Initialise(p, engine); // Target 00840 m_EventSource.Initialise(p->GetArgN(1), engine); 00841 m_EventType = (enum EventType)p->GetArgN(2)->GetEnumValue(); 00842 00843 if (p->GetArgCount() >= 4) 00844 { 00845 // TODO: We could check here that we only have bool, int or string and not object ref or content ref. 00846 m_EventData.Initialise(p->GetArgN(3), engine); 00847 } 00848 } 00849 00850 void MHSendEvent::PrintArgs(FILE *fd, int) const 00851 { 00852 m_EventSource.PrintMe(fd, 0); 00853 QByteArray tmp = MHLink::EventTypeToString(m_EventType).toAscii(); 00854 fprintf(fd, "%s", tmp.constData()); 00855 fprintf(fd, " "); 00856 00857 if (m_EventData.m_Type != MHParameter::P_Null) 00858 { 00859 m_EventData.PrintMe(fd, 0); 00860 } 00861 } 00862 00863 void MHSendEvent::Perform(MHEngine *engine) 00864 { 00865 // The target is always the current scene so we ignore it here. 00866 MHObjectRef target, source; 00867 m_Target.GetValue(target, engine); // TODO: Check this is the scene? 00868 m_EventSource.GetValue(source, engine); 00869 00870 // Generate the event. 00871 if (m_EventData.m_Type == MHParameter::P_Null) 00872 { 00873 engine->EventTriggered(engine->FindObject(source), m_EventType); 00874 } 00875 else 00876 { 00877 MHUnion data; 00878 data.GetValueFrom(m_EventData, engine); 00879 engine->EventTriggered(engine->FindObject(source), m_EventType, data); 00880 } 00881 } 00882 00883 void MHSetTimer::Initialise(MHParseNode *p, MHEngine *engine) 00884 { 00885 MHElemAction::Initialise(p, engine); 00886 m_TimerId.Initialise(p->GetArgN(1), engine); // The timer id 00887 00888 if (p->GetArgCount() > 2) 00889 { 00890 MHParseNode *pNewTimer = p->GetArgN(2); 00891 m_TimerValue.Initialise(pNewTimer->GetSeqN(0), engine); 00892 00893 if (pNewTimer->GetSeqCount() > 1) 00894 { 00895 m_TimerType = ST_TimerAbsolute; // May be absolute - depends on the value. 00896 m_AbsFlag.Initialise(pNewTimer->GetSeqN(1), engine); 00897 } 00898 else 00899 { 00900 m_TimerType = ST_TimerRelative; 00901 } 00902 } 00903 } 00904 00905 void MHSetTimer::PrintArgs(FILE *fd, int /*nTabs*/) const 00906 { 00907 m_TimerId.PrintMe(fd, 0); 00908 00909 if (m_TimerType != ST_NoNewTimer) 00910 { 00911 fprintf(fd, "( "); 00912 m_TimerValue.PrintMe(fd, 0); 00913 00914 if (m_TimerType == ST_TimerAbsolute) 00915 { 00916 m_AbsFlag.PrintMe(fd, 0); 00917 } 00918 00919 fprintf(fd, ") "); 00920 } 00921 } 00922 00923 void MHSetTimer::Perform(MHEngine *engine) 00924 { 00925 int nTimerId = m_TimerId.GetValue(engine); 00926 bool fAbsolute = false; // Defaults to relative time. 00927 int newTime = -1; 00928 00929 switch (m_TimerType) 00930 { 00931 case ST_NoNewTimer: 00932 fAbsolute = true; 00933 newTime = -1; 00934 break; // We treat an absolute time of -1 as "cancel" 00935 case ST_TimerAbsolute: 00936 fAbsolute = m_AbsFlag.GetValue(engine); // And drop to the next 00937 case ST_TimerRelative: 00938 newTime = m_TimerValue.GetValue(engine); 00939 } 00940 00941 Target(engine)->SetTimer(nTimerId, fAbsolute, newTime, engine); 00942 } 00943 00944 void MHPersistent::Initialise(MHParseNode *p, MHEngine *engine) 00945 { 00946 MHElemAction::Initialise(p, engine); // Target 00947 m_Succeeded.Initialise(p->GetArgN(1), engine); 00948 MHParseNode *pVarSeq = p->GetArgN(2); 00949 00950 for (int i = 0; i < pVarSeq->GetSeqCount(); i++) 00951 { 00952 MHObjectRef *pVar = new MHObjectRef; 00953 m_Variables.Append(pVar); 00954 pVar->Initialise(pVarSeq->GetSeqN(i), engine); 00955 } 00956 00957 m_FileName.Initialise(p->GetArgN(3), engine); 00958 } 00959 00960 void MHPersistent::PrintArgs(FILE *fd, int nTabs) const 00961 { 00962 m_Succeeded.PrintMe(fd, nTabs); 00963 fprintf(fd, " ( "); 00964 00965 for (int i = 0; i < m_Variables.Size(); i++) 00966 { 00967 m_Variables.GetAt(i)->PrintMe(fd, 0); 00968 } 00969 00970 fprintf(fd, " ) "); 00971 m_FileName.PrintMe(fd, nTabs); 00972 } 00973 00974 void MHPersistent::Perform(MHEngine *engine) 00975 { 00976 MHObjectRef target; 00977 m_Target.GetValue(target, engine); // Get the target - this should always be the application 00978 MHOctetString fileName; 00979 m_FileName.GetValue(fileName, engine); 00980 bool fResult = engine->LoadStorePersistent(m_fIsLoad, fileName, m_Variables); 00981 engine->FindObject(m_Succeeded)->SetVariableValue(fResult); 00982 } 00983 00984 MHTransitionTo::MHTransitionTo(): MHElemAction(":TransitionTo") 00985 { 00986 m_fIsTagged = false; 00987 m_nConnectionTag = 0; 00988 m_nTransitionEffect = -1; 00989 } 00990 00991 void MHTransitionTo::Initialise(MHParseNode *p, MHEngine *engine) 00992 { 00993 MHElemAction::Initialise(p, engine); // Target 00994 // The next one may be present but NULL in binary. 00995 if (p->GetArgCount() > 1) 00996 { 00997 MHParseNode *pCtag = p->GetArgN(1); 00998 00999 if (pCtag->m_nNodeType == MHParseNode::PNInt) 01000 { 01001 m_fIsTagged = true; 01002 m_nConnectionTag = pCtag->GetIntValue(); 01003 } 01004 } 01005 01006 if (p->GetArgCount() > 2) 01007 { 01008 MHParseNode *pTrEff = p->GetArgN(2); 01009 m_nTransitionEffect = pTrEff->GetIntValue(); 01010 } 01011 } 01012 01013 void MHTransitionTo::PrintArgs(FILE *fd, int /*nTabs*/) const 01014 { 01015 if (m_fIsTagged) 01016 { 01017 fprintf(fd, " %d ", m_nConnectionTag); 01018 } 01019 else if (m_nTransitionEffect >= 0) 01020 { 01021 fprintf(fd, " NULL "); 01022 } 01023 01024 if (m_nTransitionEffect >= 0) 01025 { 01026 fprintf(fd, " %d", m_nTransitionEffect); 01027 } 01028 } 01029 01030 // Do the action - Transition to a new scene. 01031 void MHTransitionTo::Perform(MHEngine *engine) 01032 { 01033 MHObjectRef target; 01034 m_Target.GetValue(target, engine); // Get the target 01035 engine->TransitionToScene(target); 01036 } 01037 01038 void MHLaunch::Perform(MHEngine *engine) 01039 { 01040 MHObjectRef target; 01041 m_Target.GetValue(target, engine); 01042 engine->Launch(target); 01043 } 01044 void MHQuit::Perform(MHEngine *engine) 01045 { 01046 engine->Quit(); 01047 } 01048 void MHSpawn::Perform(MHEngine *engine) 01049 { 01050 MHObjectRef target; 01051 m_Target.GetValue(target, engine); 01052 engine->Spawn(target); 01053 } 01054 void MHLockScreen::Perform(MHEngine *engine) 01055 { 01056 engine->LockScreen(); 01057 } 01058 void MHUnlockScreen::Perform(MHEngine *engine) 01059 { 01060 engine->UnlockScreen(); 01061 } 01062 01063 void MHGetEngineSupport::Initialise(MHParseNode *p, MHEngine *engine) 01064 { 01065 MHElemAction::Initialise(p, engine); 01066 m_Feature.Initialise(p->GetArgN(1), engine); 01067 m_Answer.Initialise(p->GetArgN(2), engine); 01068 } 01069 01070 void MHGetEngineSupport::Perform(MHEngine *engine) 01071 { 01072 // Ignore the target which isn't used. 01073 MHOctetString feature; 01074 m_Feature.GetValue(feature, engine); 01075 engine->FindObject(m_Answer)->SetVariableValue(engine->GetEngineSupport(feature)); 01076 }
1.7.6.1