smlparse.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:879k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- // system
- #include <time.h>
- #include <math.h>
- #if defined(_UNIX) && (!(defined(_BEOS))) && (!(defined(_MAC_UNIX)))
- /*for Display and Screen structs and X functions:*/
- #include "hlxclib/string.h"
- #include <X11/X.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xos.h>
- #include <sys/types.h>
- #endif
- #if defined (_SYMBIAN)
- #include <hal.h>
- #include <coemain.h>
- #include <e32svr.h>
- #include <e32math.h>
- #endif
- // include
- #include "hxtypes.h"
- #include "hxwintyp.h"
- #include "hxcom.h"
- #include "hxcomm.h"
- #include "hxprefs.h"
- #include "hxxml.h"
- #include "hxmon.h"
- #include "smiltype.h"
- #include "hxupgrd.h"
- // pncont
- #include "chxpckts.h"
- #include "hxstring.h"
- #include "hxslist.h"
- #include "rtsputil.h"
- #include "hxstack.h"
- // pnmisc
- #include "nptime.h"
- #include "smpte.h"
- #include "hxstrutl.h"
- #include "hxurl.h"
- #include "hxparse.h"
- #include "hxwinver.h"
- #include "dbcs.h" /* for HXGetNextChar() */
- // rnxmllib
- #include "xmlreslt.h"
- #include "hxxmlprs.h"
- // rmasmil
- #include "smlelem.h"
- #include "smltime.h"
- #include "smlerror.h"
- #include "smlprstime.h"
- #include "animattr.h"
- #include "binrymap.h"
- #include "smlparse.h"
- #include "parstabl.h"
- #include "smlutil.h"
- // pndebug
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- #define TARGET_OF_LINK_DESTINATION_SOUND_LEVEL_STR "targetOfLinkDestnSndLevel"
- #define TARGET_OF_LINK_SOURCE_SOUND_LEVEL_STR "targetOfLinkSourceSndLevel"
- #if defined(_DEBUG)
- // /#define XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL
- #if defined(XXXEHODGE_DEBUG_EXCL_TRACK_REMOVAL)
- static BOOL bFirstExclTrackChangeDebugOut = TRUE;
- #endif
- #endif
- #if defined(_DEBUG)
- // /#define XXXEHODGE_DEBUG_RESETTIMELINEELEMENTDUR_AND_DELAY
- #if defined(XXXEHODGE_DEBUG_RESETTIMELINEELEMENTDUR_AND_DELAY)
- static BOOL bFirstResetTimelineElementDuration = TRUE;
- #endif /*XXXEHODGE_DEBUG_RESETTIMELINEELEMENTDUR_AND_DELAY*/
- #endif /*_DEBUG*/
- // /This enables RealPlayer 8 (and prior) behavior when there is no explicit
- // outer time container (seq, par, [or excl in a SMIL 2.0 doc]):
- #define ALLOW_PLAYLIST_STYLE_SEQ 1
- #define DONT_ALLOW_PLAYLIST_STYLE_SEQ_IF_EXPLICIT_OUTER_TIMECONTAINER 1
- #define CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR 150 /* in milliseconds .*/
- // /XXXEH- in order to get Interop Timing #25.6 working, we had to trick the
- // core into staying alive by adding this track in slightly before the one
- // that paused it has finished:
- #define FUDGE_FACTOR_WHEN_DEFERRING_PAST_END_OF_GROUP 100 /*milliseconds*/
- #define FUDGE_FACTOR_FOR_DEFERRING_PRIOR_TO_END_OF_GROUP 500 /*milliseconds*/
- static const UINT32 MAX_DRIVER_PACKET_SIZE = 1024;
- static const UINT32 INITIAL_STREAM1_TIMESTAMP = 1;
- static const UINT32 INITIAL_STREAM0_TIMESTAMP = 0;
- static const UINT32 MAX_ERROR_LEN = 1024;
- static const char* const RN_PREFIX = "rn";
- static const char* const RN_TAG_RENDERER_LIST = "rn:renderer-list";
- static const char* const RN_TAG_RENDERER = "rn:renderer";
- static const char* const SYSTEM_COMPONENT_NAMESPACE = "http://features.real.com/systemComponent";
- static const char* const SYSTEM_COMPONENT = "systemComponent";
- // /These are all the SMIL Module namespaces recognized by the
- // SMIL 2.0 Language:
- // (From http://www.w3.org/AudioVideo/Group/Modules/
- // smil-modules.html#smilModulesNSSMIL20ModuleIdentifiers)
- const char* const CSmilParser::zm_pSupportedSMIL2ModuleNamespaces[
- NUM_SUPPORTED_SMIL_2_0_MODULE_NAMESPACES+1] =
- {
- // /XXXEH- TODO: OPTIMIZATION: these all share the same base URL, so
- // we should just store the last part here and combine with the base
- // when comparing to a used namespace:
- "http://www.w3.org/2000/SMIL20/CR/NestedTimeContainers",
- "http://www.w3.org/2000/SMIL20/CR/DeprecatedFeatures",
- "http://www.w3.org/2000/SMIL20/CR/HostLanguage",
- #if defined(HANDLE_CATCHALL_NS_FOR_ALL_SMIL_2_0_MODULES)
- "http://www.w3.org/2000/SMIL20/CR/",
- #else
- "",
- #endif
- "http://www.w3.org/2000/SMIL20/CR/Language",
- "http://www.w3.org/2000/SMIL20/CR/IntegrationSet",
- // /The rest are SMIL 2.0 Module namespaces:
- "http://www.w3.org/2000/SMIL20/CR/AccessKeyTiming",
- "http://www.w3.org/2000/SMIL20/CR/AudioLayout",
- "http://www.w3.org/2000/SMIL20/CR/BasicAnimation",
- "http://www.w3.org/2000/SMIL20/CR/BasicContentControl",
- "http://www.w3.org/2000/SMIL20/CR/BasicInlineTiming",
- "http://www.w3.org/2000/SMIL20/CR/BasicLayout",
- "http://www.w3.org/2000/SMIL20/CR/BasicLinking",
- "http://www.w3.org/2000/SMIL20/CR/BasicMedia",
- "http://www.w3.org/2000/SMIL20/CR/BasicTimeContainers",
- "http://www.w3.org/2000/SMIL20/CR/BasicTransistions",
- "http://www.w3.org/2000/SMIL20/CR/BrushMedia",
- "http://www.w3.org/2000/SMIL20/CR/CoordinatedTransitions",
- "http://www.w3.org/2000/SMIL20/CR/CustomTestAttributes",
- "http://www.w3.org/2000/SMIL20/CR/EventTiming",
- "http://www.w3.org/2000/SMIL20/CR/ExclTimeContainers",
- "http://www.w3.org/2000/SMIL20/CR/FillDefault",
- "http://www.w3.org/2000/SMIL20/CR/HierarchicalLayout",
- #if defined(HANDLE_SMIL_2_0_INLINETRANSITIONS_MODULE)
- "http://www.w3.org/2000/SMIL20/CR/InlineTransitions",
- #else
- "",
- #endif
- "http://www.w3.org/2000/SMIL20/CR/LinkingAttributes",
- "http://www.w3.org/2000/SMIL20/CR/MediaAccessibility",
- "http://www.w3.org/2000/SMIL20/CR/MediaClipMarkers",
- "http://www.w3.org/2000/SMIL20/CR/MediaClipping",
- "http://www.w3.org/2000/SMIL20/CR/MediaDescription",
- "http://www.w3.org/2000/SMIL20/CR/MediaMarkerTiming",
- "http://www.w3.org/2000/SMIL20/CR/MediaParam",
- "http://www.w3.org/2000/SMIL20/CR/Metainformation",
- "http://www.w3.org/2000/SMIL20/CR/MinMaxTiming",
- "http://www.w3.org/2000/SMIL20/CR/MultiArcTiming",
- "http://www.w3.org/2000/SMIL20/CR/MultiWindowLayout",
- "http://www.w3.org/2000/SMIL20/CR/ObjectLinking",
- "http://www.w3.org/2000/SMIL20/CR/PrefetchControl",
- "http://www.w3.org/2000/SMIL20/CR/PrevTiming",
- "http://www.w3.org/2000/SMIL20/CR/RepeatTiming",
- "http://www.w3.org/2000/SMIL20/CR/RepeatValueTiming",
- "http://www.w3.org/2000/SMIL20/CR/RestartDefault",
- "http://www.w3.org/2000/SMIL20/CR/RestartTiming",
- "http://www.w3.org/2000/SMIL20/CR/SkipContentControl",
- #if defined(HANDLE_SMIL_2_0_SPLINEANIMATION_MODULE)
- "http://www.w3.org/2000/SMIL20/CR/SplineAnimation",
- #else
- "",
- #endif
- "http://www.w3.org/2000/SMIL20/CR/Structure",
- "http://www.w3.org/2000/SMIL20/CR/SyncbaseTiming",
- "http://www.w3.org/2000/SMIL20/CR/SyncBehavior",
- "http://www.w3.org/2000/SMIL20/CR/SyncBehaviorDefault",
- #if defined(HANDLE_SMIL_2_0_SYNCMASTER_MODULE)
- "http://www.w3.org/2000/SMIL20/CR/SyncMaster",
- #else
- "",
- #endif
- "http://www.w3.org/2000/SMIL20/CR/TimeContainerAttributes",
- #if defined(HANDLE_SMIL_2_0_TIME_MANIPULATIONS_MODULE)
- "http://www.w3.org/2000/SMIL20/CR/TimeManipulations",
- #else
- "",
- #endif
- "http://www.w3.org/2000/SMIL20/CR/TransitionModifiers",
- "http://www.w3.org/2000/SMIL20/CR/WallclockTiming",
- "http://www.3gpp.org/SMIL20/PSS4/",
- "http://www.3gpp.org/SMIL20/PSS5/",
- NULL
- };
- static const struct smilTagTable
- {
- SMILNodeTag m_tag;
- const char* m_name;
- } SmilTagTable[] =
- {
- {SMILSmil, "smil"},
- {SMILMeta, "meta"},
- {SMILMetadata, "metadata"},
- {SMILHead, "head"},
- {SMILBody, "body"},
- {SMILBasicLayout, "layout"},
- {SMILRootLayout, "root-layout"},
- {SMILRegion, "region"},
- {SMILRegPoint, "regPoint"},
- {SMILViewport, "topLayout"},
- {SMILTransition, "transition"},
- {SMILSwitch, "switch"},
- {SMILText, "text"},
- {SMILImg, "img"},
- {SMILRef, "ref"},
- {SMILAudio, "audio"},
- {SMILVideo, "video"},
- {SMILAnimation, "animation"},
- {SMILTextstream, "textstream"},
- {SMILBrush, "brush"},
- {SMILPrefetch, "prefetch"},
- {SMILAnchor, "anchor"},
- {SMILArea, "area"},
- {SMILAAnchor, "a"},
- {SMILPar, "par"},
- {SMILSeq, "seq"},
- {SMILExcl, "excl"},
- {SMILPriorityClass, "priorityClass"},
- {SMILCustomAttributes, "customAttributes"},
- {SMILCustomTest, "customTest"},
- {SMILRNRendererList, RN_TAG_RENDERER_LIST},
- {SMILRendererPreFetch, RN_TAG_RENDERER},
- {SMILAnimate, "animate"},
- {SMILSet, "set"},
- {SMILAnimateMotion, "animateMotion"},
- {SMILAnimateColor, "animateColor"},
- {SMILUnknown, "unknown"}
- };
- SMILNamespace::SMILNamespace(SMILNamespace* pNS)
- {
- if (pNS)
- {
- m_name = new_string(pNS->m_name);
- m_pValue = pNS->m_pValue;
- if (m_pValue)
- {
- m_pValue->AddRef();
- }
- }
- }
- SMILNamespace::SMILNamespace(const char* name, IHXBuffer* pVal)
- {
- m_name = new_string(name);
- m_pValue = pVal;
- if (m_pValue)
- {
- m_pValue->AddRef();
- }
- }
- SMILNamespace::~SMILNamespace()
- {
- HX_VECTOR_DELETE(m_name);
- HX_RELEASE(m_pValue);
- }
- CSmilParser::CSmilParser(IUnknown* pContext):
- m_pContext(pContext),
- m_pClassFactory(NULL),
- m_pISystemRequired(NULL),
- m_pNodeList(0),
- m_pNodeListStack(0),
- m_pPacketQueue(0),
- m_pIDMap(0),
- m_pAddGroupMap(0),
- m_pSourceUpdateList(0),
- m_pRequireTagsMap(0),
- m_pCustomTestMap(NULL),
- m_bNoNamespaces(FALSE),
- m_bRNNamespace(FALSE),
- // XXXJHUG -- shouldn't we always ignor?
- m_bIgnoreUnrecognizedElements(TRUE),
- m_bSMILRootLayoutAlreadyFound(FALSE),
- m_pActiveNamespaceMap(NULL),
- m_pNSConflictList(NULL),
- m_bTimestampsResolved(FALSE),
- m_pCurNode(0),
- m_pNodeDependencies(0),
- m_pCurrentDependentNode(0),
- m_pAnchorStack(0),
- m_pCurrentAnchor(0),
- m_lLastCheckPendingTime(-1),
- m_ulBandwidthPreference(0),
- m_ulScreenHeightPreference(0),
- m_ulScreenWidthPreference(0),
- m_ulScreenDepthPreference(0),
- m_pLanguagePreferenceList(0),
- m_bCaptionsPreference(FALSE),
- m_pOverdubOrCaptionPreference(0),
- m_bSystemAudioDescPreference(FALSE),
- m_bUseSystemCPU(TRUE), // /If regkey not present, treat as "TRUE"
- m_bUseSystemOS(TRUE), // /If regkey not present, treat as "TRUE"
- m_pBasePath(0),
- m_pTagAttributeMap(0),
- m_bContainsSource(FALSE),
- m_bContainsInitiallyScheduledTrack(FALSE),
- m_ulDurIfNoInitialTracksScheduled(DEFAULT_DUR_IF_NO_SOURCES_SCHEDULED),
- m_pEncoding(0),
- m_pTrackHintList(0),
- m_pParser(NULL),
- m_pResponse(NULL),
- m_ulErrorLineNumber(0),
- m_ulErrorColumnNumber(0),
- m_pErrorText(NULL)
- , m_bStoreErrors(FALSE)
- , m_pErrors(NULL)
- , m_pBeginTimeSyncList(NULL)
- , m_pEndTimeSyncList(NULL)
- , m_pBeginEventList(NULL)
- , m_pEndEventList(NULL)
- , m_pBeginMediaMarkerList(NULL)
- , m_pEndMediaMarkerList(NULL)
- , m_pClipBeginMarkerList(NULL)
- , m_pClipEndMarkerList(NULL)
- , m_pPendingBeginTimeList(NULL)
- , m_pPendingEndTimeList(NULL)
- , m_pOnLoadURLList(NULL)
- , m_pOnLoadURLListCopyForPostSeek(NULL)
- , m_bHandlePostSeekOnLoadURLs(FALSE)
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- , m_pTransitionMap(NULL)
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- , m_bFirstPacket(TRUE)
- , m_pDefaultNamespace(NULL)
- , m_ulPlatformVer(HX_PLATFORM_UNKNOWN)
- , m_ulPersistentComponentID(0)
- , m_ulPersistentComponentDelay(0)
- , m_ulPersistentComponentDuration(0)
- , m_bAllowPlaylistBehavior(FALSE)
- , m_elementWithinTag(WithinUnknown)
- , m_pElementMap(NULL)
- , m_pAttributeMap(NULL)
- #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
- , m_pExtElementMap(NULL)
- , m_pExtAttributeMap(NULL)
- , m_pNamespaceMap(NULL)
- , m_pLegalAttrMap(NULL)
- , m_pContentModelMap(NULL)
- , m_pAttrType(NULL)
- , m_ppEnumAttrMap(NULL)
- , m_ppReqAttrList(NULL)
- #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
- , m_pValNSList(NULL)
- , m_pXMMFElementList(NULL)
- , m_lParseError(HXR_OK)
- , m_pAnimateElementList(NULL)
- , m_pBeginTimeMap(NULL)
- , m_pEndTimeMap(NULL)
- , m_pExternalEventList(NULL)
- , m_pExternalEventListPos(NULL)
- , m_bAllTracksNeedReflushHint(FALSE)
- , m_pElementsWithHandlerList(NULL)
- , m_pVarName(NULL)
- , m_ulNextVar(1024)
- , m_pTimelineElementManager(NULL)
- {
- if(m_pContext)
- {
- m_pContext->AddRef();
- m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pClassFactory);
- }
- initRequireTags();
- initTagAttributes();
- getPreferences();
- initParsingMaps();
- m_versionInfo.dwPlatformId = HX_PLATFORM_UNKNOWN;
- m_versionInfo.dwMachineType = HX_MACHINE_UNKNOWN;
- // /Get the OS and CPU version information:
- m_ulPlatformVer = HXGetWinVer(&m_versionInfo);
- // Allocate the variable name buffer
- m_pVarName = new char [256];
- // Allocate the timeline element manager
- m_pTimelineElementManager = new CSmilTimelineElementManager;
- }
- CSmilParser::~CSmilParser()
- {
- deleteTagAttributes();
- HX_DELETE(m_pRequireTagsMap);
- HX_DELETE(m_pCustomTestMap);
- HX_DELETE(m_pElementMap);
- HX_DELETE(m_pAttributeMap);
- #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
- HX_DELETE(m_pExtElementMap);
- HX_DELETE(m_pExtAttributeMap);
- HX_DELETE(m_pNamespaceMap);
- HX_DELETE(m_pLegalAttrMap);
- HX_DELETE(m_pContentModelMap);
- HX_VECTOR_DELETE(m_pAttrType);
- deleteEnumAttrMaps();
- deleteReqAttrLists();
- #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
- HX_DELETE(m_pAnimateElementList);
- deleteValidationNamespaceList();
- if (m_pErrors)
- {
- int size = m_pErrors->GetSize();
- for (int i =0; i < size; ++i)
- {
- IHXBuffer* pBuf = (IHXBuffer*)(*m_pErrors)[i];
- HX_RELEASE(pBuf);
- (*m_pErrors)[i] = NULL;
- }
- HX_DELETE(m_pErrors);
- }
- if (m_pActiveNamespaceMap != NULL)
- {
- CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
- for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
- {
- IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
- HX_RELEASE(pBuffer);
- }
- HX_DELETE(m_pActiveNamespaceMap);
- }
- if (m_pNSConflictList != NULL)
- {
- CHXSimpleList::Iterator ndx = m_pNSConflictList->Begin();
- for (; ndx != m_pNSConflictList->End(); ++ndx)
- {
- SMILNamespace* pNS = (SMILNamespace*)(*ndx);
- HX_DELETE(pNS);
- }
- HX_DELETE(m_pNSConflictList);
- }
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- HX_DELETE(m_pTransitionMap);
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- // /XXXEH- TODO: check mem leaks; should be clean already...
- HX_DELETE(m_pBeginTimeSyncList);
- HX_DELETE(m_pEndTimeSyncList);
- // /XXXEH- TODO: check mem leaks; should be clean already...
- HX_DELETE(m_pBeginEventList);
- HX_DELETE(m_pEndEventList);
- // /XXXEH- TODO: check mem leaks; should be clean already...
- HX_DELETE(m_pBeginMediaMarkerList);
- HX_DELETE(m_pEndMediaMarkerList);
- HX_DELETE(m_pXMMFElementList);
- HX_DELETE(m_pClipBeginMarkerList);
- HX_DELETE(m_pClipEndMarkerList);
- // /XXXEH- TODO: check mem leaks; should be clean already...
- HX_DELETE(m_pPendingBeginTimeList);
- HX_DELETE(m_pPendingEndTimeList);
- HX_DELETE(m_pOnLoadURLList);
- HX_DELETE(m_pOnLoadURLListCopyForPostSeek);
- HX_DELETE(m_pNodeDependencies);
- HX_DELETE(m_pAnchorStack);
- HX_VECTOR_DELETE(m_pEncoding);
- if(m_pLanguagePreferenceList)
- {
- CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
- for(; i != m_pLanguagePreferenceList->End(); ++i)
- {
- char* pLang = (char*)(*i);
- delete[] pLang;
- }
- HX_DELETE(m_pLanguagePreferenceList);
- }
- HX_DELETE(m_pOverdubOrCaptionPreference);
- HX_DELETE(m_pBasePath);
- close();
- HX_RELEASE(m_pClassFactory);
- HX_RELEASE(m_pContext);
- HX_VECTOR_DELETE(m_pVarName);
- HX_DELETE(m_pTimelineElementManager);
- }
- void
- CSmilParser::initRequireTags()
- {
- //XXXBAB - add required tags here
- #if 0
- m_pRequireTagsMap = new CHXMapStringToOb;
- (*m_pRequireTagsMap)["foo-require"] = 0;
- (*m_pRequireTagsMap)["boo-require"] = 0;
- #endif
- }
- void
- CSmilParser::GetSystemScreenInfo(REF(UINT32) rulScreenHeight,
- REF(UINT32) rulScreenWidth,
- REF(UINT32) rulScreenBitDepth)
- {
- rulScreenHeight = rulScreenWidth = rulScreenBitDepth = 0;
- #if defined(_WINDOWS)
- rulScreenHeight = (UINT32)GetSystemMetrics(SM_CYSCREEN);
- rulScreenWidth = (UINT32)GetSystemMetrics(SM_CXSCREEN);
- HDC hDCMain = GetDC(NULL); // /Get screen DC.
- if (hDCMain)
- {
- rulScreenBitDepth = (UINT32)GetDeviceCaps(hDCMain, BITSPIXEL);
- ReleaseDC(NULL, hDCMain);
- }
- #elif defined(_UNIX) && (!(defined(_BEOS))) && (!(defined(_MAC_UNIX)))
- // /Pass NULL string to XOpenDisplay to get default display, which
- // is the one that we're playing to:
- Display* pDisplay = XOpenDisplay(NULL);
- if (pDisplay)
- {
- Screen* pScreen = XDefaultScreenOfDisplay(pDisplay);
- rulScreenHeight = (UINT32)HeightOfScreen(pScreen);
- rulScreenWidth = (UINT32)WidthOfScreen(pScreen);
- rulScreenBitDepth = (UINT32)DefaultDepthOfScreen(pScreen);
- }
- #elif defined(_MACINTOSH) || defined(_MAC_UNIX)
- // /XXXEH- note: on a Mac, you can have multiple display devices and our
- // player can actually play to more than one at once, and can be dragged
- // from one to the other while running. Dynamic re-evaluation is needed.
- GDHandle mainGD = ::GetMainDevice();
- rulScreenHeight = (UINT32)((**mainGD).gdRect.bottom - (**mainGD).gdRect.top);
- rulScreenWidth = (UINT32)((**mainGD).gdRect.right - (**mainGD).gdRect.left);
- PixMapHandle pmh = (**mainGD).gdPMap;
- if (pmh)
- {
- rulScreenBitDepth = (UINT32)((**pmh).pixelSize);
- }
- #elif defined(_SYMBIAN)
- TInt aValue;
- TReal aTrg1;
- TReal aTrg2;
- TInt log1;
- TInt log2;
- HAL::Get(HALData::EDisplayColors,aValue);
- TScreenInfoV01 screenInfo;
- TPckg<TScreenInfoV01> si(screenInfo);
- UserSvr::ScreenInfo(si);
- rulScreenWidth = screenInfo.iScreenSize.iWidth;
- rulScreenHeight = screenInfo.iScreenSize.iHeight;
- log1 = Math::Ln(aTrg1,aValue);
- log2 = Math::Ln(aTrg2,2);
- rulScreenBitDepth = (TUint32)(aTrg1/aTrg2);
- #else
- HX_ASSERT(0 && "Contact ehodge: need screen info from this OS");
- #endif
- }
- void
- CSmilParser::getPreferences()
- {
- IHXPreferences* pPrefs = 0;
- IHXRegistry* pRegistry = NULL;
- m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
- if(HXR_OK == m_pContext->QueryInterface(
- IID_IHXPreferences, (void**)&pPrefs))
- {
- IHXBuffer* pBuf = 0;
- CHXString strTemp;
- strTemp.Format("%s.%s",HXREGISTRY_PREFPROPNAME,"Language");
- if(pRegistry && HXR_OK == pRegistry->GetStrByName(strTemp, pBuf))
- {
- // language preference can be a comma-separated list
- const char* pLang = (const char*)pBuf->GetBuffer();
- // gonna call strtok, so copy the string...
- char* pLangCopy = new_string(pLang);
- m_pLanguagePreferenceList = new CHXSimpleList;
- char* pTok = strtok(pLangCopy, ",");
- while(pTok)
- {
- // /Fixes TLC-set part of PR 58151: sometimes this list will
- // have tokens separated by ", " instead of just ",", so first
- // remove all whitespace chars after the ',' (and, if we run
- // into a whitespace-only string, go past the next comma):
- while (isspace(*pTok) || ',' == *pTok)
- {
- *pTok++;
- }
- if (' ' == *pTok)
- {
- break; // /Whitespace-only or emtpy string is not valid.
- }
- char* pLangString = new_string(pTok);
- m_pLanguagePreferenceList->AddTail(pLangString);
- pTok = strtok(NULL, ",");
- }
- delete[] pLangCopy;
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("bandwidth", pBuf) ||
- // /Fixes PR 84098 (SMIL 2.0 version): on Mac, player registry
- // is case-sensitive and the registry value is Bandwidth
- // with a capital B:
- HXR_OK == pPrefs->ReadPref("Bandwidth", pBuf))
- {
- m_ulBandwidthPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- UINT32 rulScreenHeight = 0;
- UINT32 rulScreenWidth = 0;
- UINT32 rulScreenBitDepth = 0;
- // /Each value found here will be used if the player prefs does not
- // already contain it. For PR 58072 and PR 58075:
- GetSystemScreenInfo(rulScreenHeight, rulScreenWidth, rulScreenBitDepth);
- if(HXR_OK == pPrefs->ReadPref("screen_depth", pBuf))
- {
- m_ulScreenDepthPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- // /Fixes PR 58075: if not in the player registry, then use the
- // screen (bit) depth obtained from the OS API call:
- else
- {
- m_ulScreenDepthPreference = rulScreenBitDepth;
- }
- if(HXR_OK == pPrefs->ReadPref("screen_height", pBuf))
- {
- m_ulScreenHeightPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- // /Fixes height part of PR 58072: if not in the player registry, then
- // use the screen height obtained from the OS API call:
- else
- {
- m_ulScreenHeightPreference = rulScreenHeight;
- }
- if(HXR_OK == pPrefs->ReadPref("screen_width", pBuf))
- {
- m_ulScreenWidthPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- // /Fixes width part of PR 58072: if not in the player registry, then
- // use the screen width obtained from the OS API call:
- else
- {
- m_ulScreenWidthPreference = rulScreenWidth;
- }
- if(HXR_OK == pPrefs->ReadPref("caption_switch", pBuf))
- {
- m_bCaptionsPreference =
- (BOOL)((UINT32)atol((const char*)pBuf->GetBuffer()));
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("overdub_or_caption", pBuf))
- {
- const char* pStr = (const char*)pBuf->GetBuffer();
- m_pOverdubOrCaptionPreference = new_string(pStr);
- // /XXXEH- TLC needs to allow BOTH captions and audio descriptions
- // so they'll need a "overdub_or_caption" option (choice) AND
- // a separate "audio_desc_switch" like "caption_switch", above.
- #define XXXEH_NEED_TLC_TO_HAVE_SEPARATE_audio_desc_AND_caption_PREFS
- #if defined(XXXEH_NEED_TLC_TO_HAVE_SEPARATE_audio_desc_AND_caption_PREFS)
- // /In our player (RP8), "caption_switch" is what gets set to
- // TRUE when *ALL* accessibility features are enabled. So,
- // it's possible to have accessibility features disabled but
- // to have overdub_or_captions set to one or the other; we need
- // to look at the caption_switch pref to see if we should enable
- // audio descriptions:
- if (m_bCaptionsPreference)
- {
- m_bSystemAudioDescPreference = !strcmp(pStr, "overdub");
- if (m_bSystemAudioDescPreference)
- {
- m_bCaptionsPreference = FALSE;
- }
- }
- #endif
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("systemAudioDesc", pBuf))
- {
- m_bSystemAudioDescPreference =
- (BOOL)((UINT32)atol((const char*)pBuf->GetBuffer()));
- HX_RELEASE(pBuf);
- }
- // /Fixes PR 64428:
- if(HXR_OK == pPrefs->ReadPref("UseSystemCPU", pBuf))
- {
- m_bUseSystemCPU =
- (BOOL)((UINT32)atol((const char*)pBuf->GetBuffer()));
- HX_RELEASE(pBuf);
- }
- // /Fixes PR 64428:
- if(HXR_OK == pPrefs->ReadPref("UseSystemOS", pBuf))
- {
- m_bUseSystemOS =
- (BOOL)((UINT32)atol((const char*)pBuf->GetBuffer()));
- HX_RELEASE(pBuf);
- }
- HX_RELEASE(pPrefs);
- }
- HX_RELEASE(pRegistry);
- }
- void
- CSmilParser::close()
- {
- HX_DELETE(m_pPacketQueue);
- HX_DELETE(m_pTrackHintList);
- HX_RELEASE(m_pResponse);
- HX_RELEASE(m_pErrorText);
- HX_RELEASE(m_pDefaultNamespace);
- if (m_pParser)
- {
- m_pParser->Close();
- HX_RELEASE(m_pParser);
- }
- HX_RELEASE(m_pISystemRequired);
- if (m_pCustomTestMap)
- {
- CHXMapStringToOb::Iterator i = m_pCustomTestMap->Begin();
- for(; i != m_pCustomTestMap->End(); ++i)
- {
- SMILNode* pNode = (SMILNode*)(*i);
- HX_DELETE(pNode->m_pElement);
- }
- HX_DELETE(m_pCustomTestMap);
- }
- if(m_pIDMap)
- {
- CHXMapStringToOb::Iterator i = m_pIDMap->Begin();
- for(; i != m_pIDMap->End(); ++i)
- {
- SMILNode* pNode = (SMILNode*)(*i);
- HX_DELETE(pNode->m_pElement);
- }
- HX_DELETE(m_pIDMap);
- }
- if(m_pAddGroupMap)
- {
- CHXMapLongToObj::Iterator i = m_pAddGroupMap->Begin();
- for(; i != m_pAddGroupMap->End(); ++i)
- {
- CSmilAddGroup* pAddGroup = (CSmilAddGroup*)(*i);
- delete pAddGroup;
- }
- HX_DELETE(m_pAddGroupMap);
- }
- if(m_pSourceUpdateList)
- {
- CHXSimpleList::Iterator i = m_pSourceUpdateList->Begin();
- for(; i != m_pSourceUpdateList->End(); ++i)
- {
- CSmilSourceUpdate* pUpdate = (CSmilSourceUpdate*)(*i);
- delete pUpdate;
- }
- HX_DELETE(m_pSourceUpdateList);
- }
- if (m_pActiveNamespaceMap)
- {
- CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
- for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
- {
- IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
- HX_RELEASE(pBuffer);
- }
- HX_DELETE(m_pActiveNamespaceMap);
- }
- if (m_pNSConflictList != NULL)
- {
- CHXSimpleList::Iterator ndx = m_pNSConflictList->Begin();
- for (; ndx != m_pNSConflictList->End(); ++ndx)
- {
- SMILNamespace* pNS = (SMILNamespace*)(*ndx);
- HX_DELETE(pNS);
- }
- HX_DELETE(m_pNSConflictList);
- }
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- HX_DELETE(m_pTransitionMap);
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- delete m_pNodeListStack;
- if(m_pNodeList)
- {
- delete m_pNodeList->m_pParentNode;
- }
- m_bFirstPacket = TRUE;
- // Clear the begin time map
- clearTimeValueMap(SmilBeginTimeList);
- // Clear the end time map
- clearTimeValueMap(SmilEndTimeList);
- // Clear and delete the custom event list
- clearExternalEventList();
- HX_DELETE(m_pExternalEventList);
- // Clear the handler list
- HX_DELETE(m_pElementsWithHandlerList);
- }
- HX_RESULT
- CSmilParser::init(BOOL bStoreErrors)
- {
- HX_RESULT rc = HXR_OK;
- close();
- m_pNodeListStack = new CHXStack;
- m_pPacketQueue = new CHXSimpleList;
- m_pIDMap = new CHXMapStringToOb;
- m_pAddGroupMap = new CHXMapLongToObj;
- m_bStoreErrors = bStoreErrors;
- if (m_bStoreErrors)
- {
- // XXXJHUG error stuff.
- // In the future if there was any reason, we could
- // store the errors in the nodes that the errors occurred in.
- // for now when we get an error notification, we will
- // just call the storeError function which will add
- // a new IHXBuffer to this array.. This will also be
- // called when problems are found with tags...
- // this will save having to walk the tree when it
- // is time to dump the errors.
- m_pErrors = new CHXPtrArray;
- }
- SMILNode* pRootNode = new SMILNode;
- pRootNode->m_id = "root";
- pRootNode->m_name = "root";
- m_pNodeList = new SMILNodeList;
- pRootNode->m_pNodeList = m_pNodeList;
- m_pNodeList->m_pParentNode = pRootNode;
- m_pNodeListStack->Push(pRootNode);
- #if !defined(USE_EXPAT_FOR_SMIL)
- //#define USE_EXPAT_FOR_SMIL
- #endif
- #ifdef USE_EXPAT_FOR_SMIL
- rc = m_pClassFactory->CreateInstance(CLSID_IHXXMLParser, (void**)&m_pParser);
- if (FAILED(rc))
- {
- // they don't have the parser... use old one?
- // Don't QI core for IID_IHXXMLParser; use our own instance.
- m_pParser = new HXXMLParser;
- if (m_pParser)
- {
- rc = HXR_OK;
- m_pParser->AddRef();
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- }
- if (SUCCEEDED(rc))
- {
- m_pResponse = new CSmilParserResponse(this);
- m_pResponse->AddRef();
- // Expat is created off the CCF.
- // In strict mode it requires 100% compliant XML.
- rc = m_pParser->Init(m_pResponse, "iso-8859-1", TRUE);
- }
- #else
- // Don't QI core for IID_IHXXMLParser; use our own instance.
- HXXMLParser* parser = new HXXMLParser();
- if (parser)
- {
- parser->AddRef();
- }
- else
- {
- rc = HXR_OUTOFMEMORY;
- }
- if (SUCCEEDED(rc))
- {
- m_pResponse = new CSmilParserResponse(this);
- m_pResponse->AddRef();
- rc = parser->Init(m_pResponse, NULL, TRUE); // strict parser
- }
- if (m_bStoreErrors && parser)
- {
- parser->InitErrorNotifier(m_pResponse);
- }
- m_pParser = (IHXXMLParser*)parser;
- #endif
- return rc;
- }
- HX_RESULT
- CSmilParser::parse(IHXBuffer* pBuffer, BOOL bIsFinal)
- {
- HX_RESULT rc = HXR_OK;
- if (m_bFirstPacket)
- {
- m_bFirstPacket = FALSE;
- time(&m_tRefTime);
- }
- rc = m_pParser->Parse(pBuffer, bIsFinal);
- if (SUCCEEDED(rc) && FAILED(m_lParseError))
- {
- rc = m_lParseError;
- }
- if(HXR_OK != rc)
- {
- m_pParser->GetCurrentLineNumber(m_ulErrorLineNumber);
- m_pParser->GetCurrentColumnNumber(m_ulErrorColumnNumber);
- HX_RELEASE(m_pErrorText);
- m_pParser->GetCurrentErrorText(m_pErrorText);
- }
- return rc;
- }
- HX_RESULT
- CSmilParser::durationResolved(const char* pID, UINT32 ulDuration,
- // /Defaults to FALSE:
- BOOL bSetByParent,
- BOOL bDurationExtendingDueToPause)
- {
- HX_RESULT rc = HXR_OK;
- SMILNode* pNode = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- if (pNode->m_pElement->m_bIndefiniteDuration)
- {
- #if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)
- goto cleanup;
- #endif
- }
- // add duration to parent element
- if(pNode &&
- pNode->m_pElement &&
- pNode->m_pElement->m_pTimelineElement)
- {
- pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration,
- bSetByParent, bDurationExtendingDueToPause);
- }
- }
- #if defined(XXXEH_OLD_SPECIAL_CASE_HANDLING_OF_INDEF_DUR)
- cleanup:
- #endif
- return rc;
- }
- BOOL AncestorEventsAreResolved(SMILNode* pNode, SMILNode* pOriginalChildNode)
- {
- if (!pNode || !pNode->m_pElement ||
- !pNode->m_pParent || pNode->m_tag == SMILBody)
- {
- return TRUE;
- }
- // /For any parent that's not a timeline element, e.g., priorityClass,
- // just ignore and return its parent's results:
- else if (!pNode->m_pElement->m_pTimelineElement)
- {
- return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode);
- }
- //Now, look to see if its duration and delay events, if any, are
- // resolved:
- if ( ( (pNode->m_pElement->m_pTimelineElement->durationEvent() &&
- !pNode->m_pElement->m_pTimelineElement->durationSet() &&
- // /Fixes 1/2 of PR 50535: don't care about duration event for child
- // itself; it's OK to add a timeline element that has an unresolved
- // end; (but if parent has unresolved end, we may need to wait):
- pNode != pOriginalChildNode) ||
- (pNode->m_pElement->m_pTimelineElement->delayEvent() &&
- !pNode->m_pElement->m_pTimelineElement->initialDelaySet()) ) &&
- //[SMIL 1.0 compliance] Helps fix PR 32578:
- //However, if we have a duration event and it's based on a child's
- // timing (as can happen via endsync="id(child)", then we want to
- // avoid this element waiting for its parent to be resolved while
- // the parent is waiting for this element to be resolved:
- (!pNode->m_pElement->m_pTimelineElement->durationEvent() ||
- SMILEventSourceID != pNode->m_pElement->m_nEndsyncEventSourceTag) )
- {
- return FALSE; //We still need to await event resolution.
- }
- //pNode is ok but its dependency ancestors may still be unresolved and
- // thus pNode may still have timing constraints from its dependency
- // ancestors due to their unresolved event(s):
- return AncestorEventsAreResolved(pNode->m_pParent, pOriginalChildNode);
- }
- HX_RESULT
- CSmilParser::adjustForNegativeOffset(const char* pID)
- {
- HX_RESULT pnresult = HXR_OK;
- SMILNode* pNode = 0;
- if(!m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- pnresult = HXR_FAILED;
- }
- else if (pNode && pNode->m_pElement &&
- !pNode->m_pElement->m_bInsertedIntoTimeline &&
- pNode->m_pParent && pNode->m_pParent->m_pElement)
- {
- // /Use syncBase, not parent here (in case parent is <a>, <switch>,
- // or <priorityClass> element); this fixes bug (PR 56233 repro case)
- // where clipBegin was calculted wrong, below, because priorityClass
- // was being used as syncbase and it had a begin time later than this:
- SMILNode* pSyncBaseNode = getSyncAncestor(pNode);
- if (!pSyncBaseNode || !pSyncBaseNode->m_pElement)
- {
- pnresult = HXR_FAILED;
- goto cleanup;
- }
- // /If we have a negative begin offset or delay which starts us
- // earlier than the begin offset or delay of our syncbase, we need
- // to do a clip-begin equal to the difference, and we need to
- // update our duration as well:
- LONG32 lParentBegin =
- // /If delay is valid, use it otherwise use valid beginOffset
- pSyncBaseNode->m_pElement->m_ulDelay != ((UINT32)-1) ?
- (LONG32)pSyncBaseNode->m_pElement->m_ulDelay :
- pSyncBaseNode->m_pElement->m_bBeginOffsetSet?
- pSyncBaseNode->m_pElement->m_lBeginOffset : 0;
- LONG32 lCurElementBegin =
- pNode->m_pElement->m_ulDelay != ((UINT32)-1) ?
- (LONG32)pNode->m_pElement->m_ulDelay :
- pNode->m_pElement->m_bBeginOffsetSet?
- pNode->m_pElement->m_lBeginOffset :
- // /In adjustForNegativeOffset():
- // /Fixes case where parent has explicit dur, explicit
- // begin offset, and pNode's element begins on an event;
- // this used to set lCurElementBegin to 0 and erroneous
- // clip-begin equal to parent's begin offset would ensue:
- MAX_LONG32;
- // /First, we need to see if this is happening during playback; if
- // so, our begin may have resolved to a time in the past that is
- // later than our sync-parent's begin; in that case, we need to
- // adjust the clip-begin and delay to account for the diff between
- // now and lCurElementBegin:
- if (m_lLastCheckPendingTime > (lCurElementBegin +
- // /(re)Fixes broken long-sync-arc test file
- // BUG-20001110_BeginOffsetInPar...BeginningOnClickAllowsSync.smi
- // where the clipBegin was being *re*-computed here, after
- // having already been adjusted in setDelay() for a long-sync-
- // arc negative offset. We shouldn't do any adjustment here
- // if the difference is very small (which is not due to
- // user or authored delay clipping, but is due to processor
- // time between when our parent resolved and when the last
- // check pending time):
- CHECKPENDING_TIME_VS_CURTIME_FUDGE_FACTOR))
- {
- lParentBegin = m_lLastCheckPendingTime;
- }
- if (lCurElementBegin < lParentBegin)
- {
- LONG32 lDiff = lParentBegin - lCurElementBegin;
- HX_ASSERT(lDiff >= 0);
- if (lDiff > 0)
- {
- ULONG32 ulPriorPureDuration = pNode->m_pElement->getPureDuration();
- ULONG32 ulDiff = (ULONG32)lDiff;
- // /If clip-begin is invalid, set it otherwise add to it:
- pNode->m_pElement->m_ulClipBegin = ((UINT32)-1 ==
- pNode->m_pElement->m_ulAuthoredClipBegin? ulDiff :
- ulDiff+pNode->m_pElement->m_ulAuthoredClipBegin);
- if ((UINT32)-1 != pNode->m_pElement->m_ulDuration)
- {
- if (pNode->m_pElement->m_ulDuration > ulDiff)
- {
- pNode->m_pElement->m_ulDuration -= ulDiff;
- }
- // /else duration is negative; it can't ever play:
- else
- {
- pNode->m_pElement->m_ulDuration = 0;
- }
- }
- // /And, we should now begin when our parent does:
- pNode->m_pElement->m_ulDelay = lParentBegin;
- // /Only reset duration if it's not 0xFFFFFFFF and
- // if it's not the same as it was before:
- if ((UINT32)-1 != pNode->m_pElement->m_ulDuration &&
- ulPriorPureDuration != pNode->m_pElement->getPureDuration())
- {
- resetTimelineElementDuration(pID,
- pNode->m_pElement->getPureDuration(),
- ulPriorPureDuration);
- }
- if (m_pTimelineElementManager) m_pTimelineElementManager->notify(pID);
- }
- }
- }
- cleanup:
- return pnresult;
- }
- void
- CSmilParser::insertTimelineElement(const char* pID, UINT32 ulDelay)
- {
- #if defined(_DEBUG) && defined(XXXEH_DEBUGOUT_ADDDURATION)
- {
- FILE* f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
- ::fprintf(f1, "CSmilParser::insertTimelineElement(%s, delay=%lu) _-_-_-_-_-_-_-_-_n",
- (const char*)pID, ulDelay);
- ::fclose(f1);
- }
- #endif
- SMILNode* pNode = 0;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- if(pNode &&
- pNode->m_pElement &&
- // /XXXEH- TODO: we need to handle restart!="never" which
- // means that the following if condition should take this
- // into account:
- !pNode->m_pElement->m_bInsertedIntoTimeline &&
- //[SMIL 1.0 compliance] Helps fix PR 16629:
- // We don't want to insert a node into the timeline if
- // its begin is dependent on another (not-yet-
- // resolved) element:
- ((!pNode->m_pElement->m_pTimelineElement->delayEvent() ||
- pNode->m_pElement->m_pTimelineElement->initialDelaySet()) )
- //[SMIL 1.0 compliance] Helps fix 14420:
- // First, we need to look all the way up the tree of ancestors
- // to see if any of them have event-based delays or durations
- // and to make sure the appropriate time(s) are resolved. If
- // not, we'll have to await those event resolutions before
- // inserting this element into the timeline:
- && AncestorEventsAreResolved(pNode, pNode)
- // /For SMIL 2.0, we can have begin="indefinite" which should
- // be treated as un unresolved event (but only if that's the
- // sole begin time specified; begin="indefinite; 5s" should be
- // treated as begin="5s"):
- && !pNode->m_pElement->m_bIndefiniteBegin
- )
- {
- ULONG32 ulDelayBeyondParentDelay = 0;
- ULONG32 ulSyncBaseDelay = 0;
- SMILNode* pSyncAncestor = getSyncAncestor(pNode);
- HX_ASSERT((UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay);
- // /Check hard time boundaries set by parent:
- if (pSyncAncestor && pSyncAncestor->m_pElement &&
- (UINT32)-1 != pSyncAncestor->m_pElement->m_ulDelay)
- {
- ulSyncBaseDelay = pSyncAncestor->m_pElement->m_ulDelay;
- ulDelayBeyondParentDelay = ulDelay - ulSyncBaseDelay;
- HX_ASSERT(ulDelay >= ulSyncBaseDelay);
- if (ulDelay < ulSyncBaseDelay)
- {
- ulDelayBeyondParentDelay = 0;
- }
- // /If child has delay beyond parent's delay+duration, i.e.,
- // begin resolved on an event or sync arc, then don't insert it:
- else
- {
- if (pSyncAncestor->m_pElement->m_bHasExplicitDur &&
- !pSyncAncestor->m_pElement->m_bIndefiniteDuration &&
- !pSyncAncestor->m_pElement->m_bIndefiniteEnd &&
- (ulDelayBeyondParentDelay >=
- pSyncAncestor->m_pElement->m_ulDuration) )
- {
- goto cleanup; //It can't ever play.
- }
- else if (pSyncAncestor->m_pElement->m_bEndOffsetSet &&
- !pSyncAncestor->m_pElement->m_bIndefiniteDuration &&
- !pSyncAncestor->m_pElement->m_bIndefiniteEnd)
- {
- if (ulDelayBeyondParentDelay >=
- pSyncAncestor->m_pElement->m_ulDuration)
- {
- goto cleanup; //It can't ever play.
- }
- }
- }
- }
- else
- {
- // /Fixes PR 50411: long sync-arc begin resolved before parent
- // begin resolved and is thus not adjusted for any offset
- // from parent begin; dur:=0 if it ends before parent begin:
- if (pSyncAncestor)
- {
- pNode->m_pElement->m_bAwaitingSyncAncestorBeginNotification=
- TRUE;
- }
- goto cleanup; // /Wait to insert this until parent is resolved.
- }
- #define XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530
- #if defined(XXXEH_ABOVE_SHOULD_HANDLE_THIS__REMOVE_IF_NO_ASSERT0_BY_20010530)
- // /[SMIL 1.0 Compliance] Fixes PR 27644:
- // if our begin offset is same or greater than our parent's
- // end offset, then we should be ignored:
- if ( pNode->m_pParent && pNode->m_pParent->m_pElement &&
- pNode->m_pElement->m_bBeginOffsetSet &&
- pNode->m_pParent->m_pElement->m_bEndOffsetSet &&
- (pNode->m_pElement->m_lBeginOffset >
- pNode->m_pParent->m_pElement->m_lEndOffset) )
- {
- // /See if above replaces this code; if no assert reported by
- // 2001-05-20, then I'm going to remove this whole if() block:
- HX_ASSERT(0 && "mailto: ehodge@real.com");
- goto cleanup; //Don't insert this because it can't ever play.
- }
- // /Also, need to check parent *dur* and make sure we don't
- // exceed it if it's been explicitly set to a finite amount:
- if ( pNode->m_pParent && pNode->m_pParent->m_pElement &&
- pNode->m_pElement->m_bBeginOffsetSet &&
- pNode->m_pParent->m_pElement->m_bHasExplicitDur &&
- !pNode->m_pParent->m_pElement->m_bIndefiniteDuration &&
- (pNode->m_pElement->m_lBeginOffset > 0 &&
- (UINT32)pNode->m_pElement->m_lBeginOffset >
- pNode->m_pParent->m_pElement->m_ulDuration) )
- {
- // /See if above replaces this code; if no assert reported by
- // 2001-05-20, then I'm going to remove this whole if() block:
- HX_ASSERT(0 && "mailto: ehodge@real.com");
- goto cleanup; //Don't insert this because it can't ever play.
- }
- #endif
- // If this element uses media markers for clipBegin
- // then those markers need to be resolved
- if (pNode->m_pElement->m_bClipBeginUsesMarker &&
- !pNode->m_pElement->m_bClipBeginMarkerResolved)
- {
- // Set the flag saying we WOULD have scheduled
- // this element except the clip begin marker wasn't
- // resolved yet.
- pNode->m_pElement->m_bWaitingOnClipBeginToResolve = TRUE;
- goto cleanup; // don't insert cause we don't know the clipBegin yet
- }
- // If this element uses media markers for clipEnd
- // then those markers need to be resolved
- if (pNode->m_pElement->m_bClipEndUsesMarker &&
- !pNode->m_pElement->m_bClipEndMarkerResolved)
- {
- // Set the flag saying we WOULD have scheduled
- // this element except the clip end marker wasn't
- // resolved yet.
- pNode->m_pElement->m_bWaitingOnClipEndToResolve = TRUE;
- goto cleanup; // don't insert cause we don't know the clipEnd yet
- }
- // skip the element if its duration == 0
- if (0 == pNode->m_pElement->m_ulDuration)
- {
- durationResolved(pNode->m_id, 0);
- }
- else
- {
- // XXXMEH - we need to know about animations that
- // involve sources before we know about the sources.
- // Therefore, we need to ensure that the animate
- // elements are put before the source elements.
- UINT32 ulTS = INITIAL_STREAM1_TIMESTAMP;
- if (pNode->m_tag == SMILAnimate ||
- pNode->m_tag == SMILSet ||
- pNode->m_tag == SMILAnimateColor ||
- pNode->m_tag == SMILAnimateMotion)
- {
- ulTS = INITIAL_STREAM0_TIMESTAMP;
- }
- pNode->m_pElement->m_ulDelay = ulDelay;
- pNode->m_pElement->m_ulTimestamp = ulTS;
- pNode->m_pElement->m_bInsertedIntoTimeline = TRUE;
- pNode->m_pElement->m_bHasBeenScheduled = TRUE;
- // /This helps fix problem where time container has multiple
- // begin conditions and, when second begin was being
- // processed, wasn't being seen as having started before so
- // prepForRestart() wasn't being called when it should.
- // Allow more than one level, i.e., recurse up the tree to
- // set this for all ancestor time containers:
- SMILNode* pNextHigherSyncAncestor = pSyncAncestor;
- while (pNextHigherSyncAncestor &&
- pNextHigherSyncAncestor->m_pElement)
- {
- pNextHigherSyncAncestor->m_pElement->m_bInsertedIntoTimeline = TRUE;
- pNextHigherSyncAncestor->m_pElement->m_bHasBeenScheduled = TRUE;
- pNextHigherSyncAncestor = getSyncAncestor(
- pNextHigherSyncAncestor);
- }
- insertElementByTimestamp(pNode->m_pElement);
- }
- }
- }
- cleanup:
- return;
- }
- HX_RESULT
- CSmilParser::trackRemoved(const char* pID,
- UINT32 ulDuration)
- {
- HX_RESULT hr = HXR_OK;
- SMILNode* pNode = NULL;
- IHXBuffer* pBuf = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- // add duration to parent element
- if(pNode &&
- pNode->m_pElement &&
- pNode->m_pElement->m_pTimelineElement)
- {
- pNode->m_pElement->m_pTimelineElement->resetDuration(ulDuration);
- }
- }
- return hr;
- }
- void
- CSmilParser::resetTimelineElementDuration(const char* pID,
- // /These durations must NOT include delay (for PR 79699 et al):
- UINT32 ulPureDuration,
- UINT32 ulPriorPureDuration)
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_RESETTIMELINEELEMENTDUR_AND_DELAY)
- {
- FILE* f1 = ::fopen("c:\smil2ResetTimelineDurOrDelay.txt", bFirstResetTimelineElementDuration?"w":"a+");
- bFirstResetTimelineElementDuration = FALSE;
- ::fprintf(f1, "Element id = %s;t%sresetting (pure) duration to %lu from %lun",
- pID, ulPureDuration==ulPriorPureDuration?
- #if XXXEH_TEST_THIS_MORE
- "Skipping ":"",
- #else
- "":"",
- #endif
- ulPureDuration, ulPriorPureDuration);
- ::fclose(f1);
- f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
- ::fprintf(f1, "nElement id = %s;t%sresetting duration to %lu from %lunn",
- pID, ulPureDuration==ulPriorPureDuration?
- #if XXXEH_TEST_THIS_MORE
- "Skipping ":"",
- #else
- "":"",
- #endif
- ulPureDuration, ulPriorPureDuration);
- ::fclose(f1);
- }
- #endif
- SMILNode* pNode = NULL;
- // /Fixes bug exposed by fixes for PR 59584 and others (by undoing the
- // original fix for PR 61174(version1) and par version of PR 56686).
- // Don't reset duration if it's the same, otherwise SourceUpdate will be
- // created possibly prior to TrackDurationSet() even being called, which
- // would cause this delay event to be used to possibly mess things up in
- // rendererInitialized():
- #if defined(XXXEH_TEST_THIS_MORE)
- // /TEST THIS! A test file fails due to this when both are same,
- // "..relatedToPR59584andPR62688(endsync1stWithRestartVersion..smil"
- if (ulPureDuration == ulPriorPureDuration)
- {
- goto cleanup;
- }
- #endif
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- CSmilSourceUpdate* pUpdate = new CSmilSourceUpdate;
- pUpdate->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
- pUpdate->m_srcID = pID;
- pUpdate->m_updateTag = UpdateDuration;
- pUpdate->m_ulUpdatedDuration = ulPureDuration;
- pUpdate->m_bDurationIsPureOfDelay = TRUE;
- if(!m_pSourceUpdateList)
- {
- m_pSourceUpdateList = new CHXSimpleList;
- }
- m_pSourceUpdateList->AddTail(pUpdate);
- insertElementByTimestamp(pUpdate);
- }
- #if defined(XXXEH_TEST_THIS_MORE)
- cleanup:
- #endif
- return;
- }
- void
- CSmilParser::resetTimelineElementDelay(const char* pID,
- UINT32 ulDelay,
- UINT32 ulPriorDelay)
- {
- #if defined(_DEBUG) && defined(XXXEHODGE_DEBUG_RESETTIMELINEELEMENTDUR_AND_DELAY)
- {
- FILE* f1 = ::fopen("c:\smil2ResetTimelineDurOrDelay.txt", bFirstResetTimelineElementDuration?"w":"a+");
- bFirstResetTimelineElementDuration = FALSE;
- ::fprintf(f1, "Element id = %s;t%sresetting delay to %lu from %lun",
- pID, ulDelay==ulPriorDelay?"Skipping ":"", ulDelay, ulPriorDelay);
- ::fclose(f1);
- f1 = ::fopen("c:\smil2AddDuration.txt", "a+");
- ::fprintf(f1, "nElement id = %s;t%sresetting delay to %lu from %lunn",
- pID, ulDelay==ulPriorDelay?"Skipping ":"", ulDelay, ulPriorDelay);
- ::fclose(f1);
- }
- #endif
- SMILNode* pNode = NULL;
- // /Fixes bug exposed by fixes for PR 59584 and others (by undoing the
- // original fix for PR 61174(version1) and par version of PR 56686).
- // Don't reset delay if it's the same, otherwise SourceUpdate will be
- // created possibly prior to TrackDurationSet() even being called, which
- // would cause this delay event to be used to possibly mess things up in
- // rendererInitialized():
- if (ulDelay == ulPriorDelay)
- {
- goto cleanup;
- }
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- CSmilSourceUpdate* pUpdate = new CSmilSourceUpdate;
- pUpdate->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
- pUpdate->m_srcID = pID;
- pUpdate->m_updateTag = UpdateDelay;
- pUpdate->m_ulUpdatedDelay = ulDelay;
- if(!m_pSourceUpdateList)
- {
- m_pSourceUpdateList = new CHXSimpleList;
- }
- m_pSourceUpdateList->AddTail(pUpdate);
- insertElementByTimestamp(pUpdate);
- }
- cleanup:
- return;
- }
- CSmilElement*
- CSmilParser::findElement(const char* pID)
- {
- SMILNode* pNode = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- return pNode->m_pElement;
- }
- return NULL;
- }
- const char*
- CSmilParser::assignID(const char* pPrefix)
- {
- SafeSprintf(m_pVarName, 256, "%s_%ld", pPrefix, GetUniqueNumber());
- return m_pVarName;
- }
- UINT16
- CSmilParser::getFragmentGroup(const char* pFragment)
- {
- if(pFragment)
- {
- SMILNode* pNode = 0;
- if(m_pIDMap->Lookup(pFragment, (void*&)pNode))
- {
- if(!pNode->m_bDelete)
- {
- if(pNode->m_tag == SMILAAnchor ||
- pNode->m_tag == SMILSwitch)
- {
- SMILNode* pChildNode = getTimelineDescendent(pNode, NULL);
- while(pChildNode)
- {
- if(!pChildNode->m_bDelete)
- {
- return pChildNode->m_nGroup;
- }
- pChildNode = getTimelineDescendent(pNode, pChildNode);
- }
- }
- else if(pNode->m_tag == SMILAnchor ||
- pNode->m_tag == SMILArea)
- {
- SMILNode* pParentNode = pNode->m_pParent;
- if(pParentNode &&
- !pParentNode->m_bDelete)
- {
- return pParentNode->m_nGroup;
- }
- }
- else
- {
- return pNode->m_nGroup;
- }
- }
- }
- }
- return 0;
- }
- UINT32
- CSmilParser::getFragmentOffset(const char* pFragment,
- //This BOOL will be set to FALSE if the fragment
- // does not exist; this was necessary to fix PR 22655.
- BOOL& bFragFoundAndResolved,
- BOOL bResolveBeginOfFragmentTarget,
- ULONG32 ulCurTime)
- {
- bFragFoundAndResolved = FALSE;
- if(pFragment)
- {
- INT32 lAnchorBegin = 0;
- SMILNode* pNode = NULL;
- CSmilElement* pElement = NULL;
- CSmilElement* pFragmentElement = NULL;
- if(m_pIDMap->Lookup(pFragment, (void*&)pNode) &&
- pNode->m_pElement)
- {
- pElement = pNode->m_pElement;
- if(pNode->m_tag == SMILSwitch ||
- pNode->m_tag == SMILAAnchor)
- {
- SMILNode* pChildNode = getTimelineDescendent(
- pNode, NULL);
- while(pChildNode)
- {
- if(!pChildNode->m_bDelete)
- {
- pFragmentElement = pChildNode->m_pElement;
- break;
- }
- pChildNode = getTimelineDescendent(
- pNode, pChildNode);
- }
- }
- else if(pNode->m_tag == SMILAnchor ||
- pNode->m_tag == SMILArea)
- {
- if(pElement->m_bBeginOffsetSet)
- {
- lAnchorBegin = pElement->m_lBeginOffset;
- }
- SMILNode* pParent = pNode->m_pParent;
- if(pParent)
- {
- pFragmentElement = pParent->m_pElement;
- }
- }
- else
- {
- pFragmentElement = pElement;
- }
- if(pFragmentElement)
- {
- bFragFoundAndResolved = TRUE;
- //[SMIL 1.0 Compliance] Fixes PR 26464:
- // Use delay (which already includes begin offset)
- // if it's a valid value, else use begin offset
- // without delay added (see comment below):
- if(pFragmentElement->m_ulDelay != (UINT32)-1)
- {
- INT32 offset = pFragmentElement->m_ulDelay +
- lAnchorBegin;
- return (offset >= 0 ? (UINT32)offset: 0);
- }
- else if(pFragmentElement->m_bBeginOffsetSet)
- {
- //Changed this while fixing PR 26464:
- // This used to return pFragmentElement->m_ulDelay +
- // pFragmentElement->m_lBeginOffset + lAnchorBegin but
- // the delay can already account for the begin if both
- // are set so we'd end up seeking past where we were
- // supposed to go by the amount of the begin offset.
- // Also, we weren't even checking to see
- // if delay was valid before using it (and now we're
- // sure it is invalid per check above):
- INT32 offset = pFragmentElement->m_lBeginOffset +
- lAnchorBegin;
- return (offset >= 0 ? (UINT32)offset: 0);
- }
- // /Fixes SMIL 2.0 Interop Linking tests #1.4 & #1.5:
- // if we've been instructed to resolve this #-ref'd
- // internally-linked element's delay, then we need to
- // do so to the current time:
- else if (bResolveBeginOfFragmentTarget &&
- pFragmentElement->m_pTimelineElement)
- {
- SMILNode* pSyncAncestor =
- getSyncAncestor(pFragmentElement->m_pNode);
- // /Fixes PR 50848:
- // /The following is needed to completely fix SMIL 2.0
- // Interop Linking #1.5 (to make the clicked-on child of
- // a seq go away when the clicked-to one starts):
- if (pSyncAncestor && SMILSeq == pSyncAncestor->m_tag)
- {
- SMILNode* pSibling = pSyncAncestor->getFirstChild();
- SMILNode* pPrevSibling = NULL;
- while (pSibling)
- {
- if (pSibling->m_id ==
- pFragmentElement->m_pNode->m_id)
- {
- break;
- }
- // /Fixes case where pFragmentElement has non-
- // timeline-element parent, e.g., <a> or <switch>
- else if (pFragmentElement->m_pNode->m_pParent !=
- pSyncAncestor)
- {
- SMILNode* pFirstSiblingChild =
- pSibling->getFirstChild();
- if (pFirstSiblingChild &&
- pFirstSiblingChild->m_id ==
- pFragmentElement->m_pNode->m_id)
- {
- break;
- }
- }
- pPrevSibling = pSibling;
- pSibling = pSyncAncestor->getNextChild();
- }
- if (pPrevSibling)
- {
- // /XXXEH- TODO: if prev sib is not a timeline
- // element, use its first child as prev sibling.
- if (pPrevSibling->m_pElement &&
- pPrevSibling->m_pElement->m_pTimelineElement)
- {
- ULONG32 ulCurStartTime = 0;
- if (HXR_OK == pPrevSibling->m_pElement->
- getCurrentScheduledStartTime(
- ulCurStartTime) &&
- ulCurTime > ulCurStartTime)
- {
- ULONG32 ulNewDuration =
- ulCurTime - ulCurStartTime;
- durationResolved(pPrevSibling->m_id,
- ulNewDuration);
- if (m_pTimelineElementManager)
- m_pTimelineElementManager->notify((const char*)pPrevSibling->m_id);
- }
- }
- }
- }
- // /If not child of seq, then just set its delay to now:
- else
- {
- pFragmentElement->m_pTimelineElement->setDelay(
- ulCurTime,FALSE);
- }
- }
- else
- {
- // /Must just be a mouse move, so return the
- // unresolved value so mouse cursor can change:
- return ((UINT32)-1);
- }
- }
- }
- }
- return 0;
- }
- SMILNode*
- CSmilParser::findFirstNode(SMILNodeList* pNodeList, SMILNodeTag tag)
- {
- if(!pNodeList)
- {
- return 0;
- }
- SMILNode* pFoundNode = 0;
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();i!=pNodeList->End();++i)
- {
- SMILNode* pNode = (SMILNode*)(*i);
- if(pNode->m_tag == tag)
- {
- pFoundNode = pNode;
- }
- else
- {
- pFoundNode = findFirstNode(pNode->m_pNodeList, tag);
- }
- if(pFoundNode)
- {
- break;
- }
- }
- return pFoundNode;
- }
- SMILNode*
- CSmilParser::findFirstNode(SMILNodeTag tag)
- {
- return findFirstNode(m_pNodeList, tag);
- }
- SMILNode*
- CSmilParser::getFirstNodeChild(SMILNode* pNode)
- {
- m_pCurNode = pNode;
- if(!m_pCurNode)
- {
- return 0;
- }
- return m_pCurNode->getFirstChild();
- }
- SMILNode*
- CSmilParser::getNextNodeChild()
- {
- if(!m_pCurNode)
- {
- return 0;
- }
- return m_pCurNode->getNextChild();
- }
- HX_RESULT
- CSmilParser::parseClockValue(const char* pValue, UINT32& ulTimeValue)
- {
- // try npt
- char* pPtr = (char *)strstr(pValue, "npt=");
- if(pPtr)
- {
- pPtr += 4; // point to beginning of clock value
- //[SMIL 1.0 compliance] fixes PR 26445: if "npt=4h" is specified,
- // we need to convert to "14400s" otherwise the 4 is treated as
- // seconds:
- char* pHourChar = strchr(pPtr, 'h');
- if (pHourChar && !strchr(pPtr, ':')) //then it's hours without ':'
- {
- IHXBuffer* pBuf = new CHXBuffer;
- if (pBuf)
- {
- pBuf->AddRef();
- *pHourChar = ' '; //get rid of the 'h' in pPtr.
- pBuf->Set((const unsigned char *)pPtr,
- strlen(pPtr) + strlen(":00:00") + 1);
- char* pTmp = (char*)pBuf->GetBuffer();
- strcat(pTmp, ":00:00"); /* Flawfinder: ignore */
- NPTime clockTime((const char*)pTmp);
- ulTimeValue = (UINT32)clockTime;
- pBuf->Release();
- }
- else
- {
- return HXR_OUTOFMEMORY;
- }
- }
- //END fix for PR 26445.
- else
- {
- NPTime clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- }
- return HXR_OK;
- }
- // try smpte
- pPtr = (char *)strstr(pValue, "smpte=");
- if(pPtr)
- {
- pPtr += 6; // point to beginning of clock value
- SMPTETimeCode clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- pPtr = (char *)strstr(pValue, "smpte-30-drop=");
- if(pPtr)
- {
- pPtr += 14; // point to beginning of clock value
- SMPTETimeCode clockTime(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- pPtr = (char *)strstr(pValue, "smpte-25=");
- if(pPtr)
- {
- pPtr += 9; // point to beginning of clock value
- SMPTETimeCode clockTime;
- clockTime.m_framesPerSec = SMPTETimeCode::FPS_25;
- clockTime.fromString(pPtr);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- else if(strchr(pValue, ':')) // try just hh:mm:ss with no prefix/suffix
- {
- NPTime clockTime(pValue);
- ulTimeValue = (UINT32)clockTime;
- return HXR_OK;
- }
- // ok, try h/min/s/ms
- char* pEndPtr = 0;
- double dVal = strtod(pValue, &pEndPtr);
- if(strcmp(pEndPtr, "h") == 0)
- {
- ulTimeValue = (UINT32)(dVal * 60.0 * 60.0 * 1000.0);
- return HXR_OK;
- }
- else if(strcmp(pEndPtr, "min") == 0)
- {
- ulTimeValue = (UINT32)(dVal * 60.0 * 1000.0);
- return HXR_OK;
- }
- else if(strcmp(pEndPtr, "s") == 0 ||
- //[SMIL 1.0 compliance] Fixes PR 22673: the SMIL doc says that we
- // need to default to seconds if no unit-type is given:
- // Timecount-val ::= Timecount ("." Fraction)?
- // ("h" | "min" | "s" | "ms")? ; default is "s"
- (!strlen(pEndPtr)) )
- {
- ulTimeValue = (UINT32)(dVal * 1000.0);
- return HXR_OK;
- }
- else if(strcmp(pEndPtr, "ms") == 0)
- {
- ulTimeValue = (UINT32)(dVal);
- return HXR_OK;
- }
- //else something other than "h", "min", "s", "", or "ms" was specified:
- else
- {
- return HXR_FAIL;
- }
- }
- HX_RESULT
- CSmilParser::parseSyncBehaviorVal(const char* pSyncBehaviorBuf,
- CSmilElement* pElement,
- SMILSyncAttributeTag nTag)
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == pSyncBehaviorBuf || (SMILSyncAttrSyncBehavior != nTag &&
- SMILSyncAttrSyncBehaviorDefault != nTag))
- {
- HX_ASSERT(FALSE);
- return HXR_UNEXPECTED;
- }
- // First, eat all whitespace:
- const char* pCh = pSyncBehaviorBuf;
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == ' ')
- {
- // nothing, empty attribute...
- return HXR_OK;
- }
- BOOL bParsedOK = TRUE;
- SMILSyncBehaviorType sbtype = SmilSyncBehaviorInvalid;
- if (strncmp(pCh, "canSlip", 7) == 0)
- {
- pCh += 7;
- sbtype = SmilSyncBehaviorCanSlip;
- }
- else if (strncmp(pCh, "locked", 6) == 0)
- {
- pCh += 6;
- sbtype = SmilSyncBehaviorLocked;
- }
- else if (strncmp(pCh, "independent", 11) == 0)
- {
- pCh += 11;
- sbtype = SmilSyncBehaviorIndependent;
- }
- else if (strncmp(pCh, "default", 7) == 0)
- {
- pCh += 7;
- sbtype = SmilSyncBehaviorDefault;
- }
- else if (strncmp(pCh, "inherit", 7) == 0)
- {
- pCh += 7;
- sbtype = SmilSyncBehaviorInherit;
- }
- else
- {
- bParsedOK = FALSE;
- }
- if (bParsedOK)
- {
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh)
- {
- bParsedOK = FALSE; // /Should only be whitespace after value.
- }
- }
- if (SMILSyncAttrSyncBehavior == nTag)
- {
- pElement->m_syncBehavior = sbtype;
- // /syncBehavior can not be "inherit":
- bParsedOK = bParsedOK && (SmilSyncBehaviorInherit != sbtype);
- }
- else
- {
- pElement->m_syncBehaviorDefault = sbtype;
- // /syncBehaviorDefault can not be "default":
- bParsedOK = bParsedOK && (SmilSyncBehaviorDefault != sbtype);
- }
- if (SmilSyncBehaviorInvalid == sbtype || !bParsedOK)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::parsePeersHigherLower(const char* pBuf,
- CSmilPriorityClassElement* pPCElement,
- SMILPriorityClassPeersHigherLowerAttrib nAttrib)
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == pBuf || (SMILPriorityClassPeers != nAttrib &&
- SMILPriorityClassHigher != nAttrib &&
- SMILPriorityClassLower != nAttrib))
- {
- HX_ASSERT(FALSE);
- return HXR_UNEXPECTED;
- }
- BOOL bParsedOK = TRUE;
- SMILPriorityClassPeersHigherLowerVal val =
- SMILPriorityClassPeersHigherLowerInvalid;
- // First, eat all whitespace:
- const char* pCh = pBuf;
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == ' ')
- {
- ret = HXR_INVALID_PARAMETER;
- goto cleanup;
- }
- if (strncmp(pCh, "stop", 4) == 0)
- {
- pCh += 4;
- val = SMILPriorityClassStop;
- }
- else if (strncmp(pCh, "pause", 5) == 0)
- {
- pCh += 5;
- val = SMILPriorityClassPause;
- }
- else if (strncmp(pCh, "defer", 5) == 0)
- {
- pCh += 5;
- val = SMILPriorityClassDefer;
- }
- else if (strncmp(pCh, "never", 5) == 0)
- {
- pCh += 5;
- val = SMILPriorityClassNever;
- }
- else
- {
- bParsedOK = FALSE;
- }
- if (bParsedOK)
- {
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh)
- {
- bParsedOK = FALSE; // /Should only be whitespace after value.
- }
- }
- if (SMILPriorityClassPeers == nAttrib)
- {
- pPCElement->m_peers = val;
- }
- else if (SMILPriorityClassHigher == nAttrib)
- {
- pPCElement->m_higher = val;
- // /higher can't be "defer" or "never":
- bParsedOK = bParsedOK && (SMILPriorityClassDefer != val &&
- SMILPriorityClassNever != val);
- }
- else // /SMILPriorityClassLower
- {
- pPCElement->m_lower = val;
- // /lower can't be "stop" or "pause":
- bParsedOK = bParsedOK && (SMILPriorityClassStop != val &&
- SMILPriorityClassPause != val);
- }
- if (SMILPriorityClassPeersHigherLowerAttribInvalid== val || !bParsedOK)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- cleanup:
- return ret;
- }
- HX_RESULT
- CSmilParser::parsePauseDisplay(const char* pBuf,
- CSmilPriorityClassElement* pPCElement)
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == pBuf)
- {
- HX_ASSERT(FALSE);
- return HXR_UNEXPECTED;
- }
- BOOL bParsedOK = TRUE;
- // First, eat all whitespace:
- const char* pCh = pBuf;
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == ' ')
- {
- ret = HXR_INVALID_PARAMETER;
- goto cleanup;
- }
- pPCElement->m_pauseDisplay = SMILPriorityClassPauseDisplayInvalid;
- if (strncmp(pCh, "disable", 7) == 0)
- {
- pCh += 7;
- pPCElement->m_pauseDisplay = SMILPriorityClassPauseDisplayDisable;
- }
- else if (strncmp(pCh, "hide", 4) == 0)
- {
- pCh += 4;
- pPCElement->m_pauseDisplay = SMILPriorityClassPauseDisplayHide;
- }
- else if (strncmp(pCh, "show", 4) == 0)
- {
- pCh += 4;
- pPCElement->m_pauseDisplay = SMILPriorityClassPauseDisplayShow;
- }
- else
- {
- bParsedOK = FALSE;
- }
- if (bParsedOK)
- {
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh)
- {
- bParsedOK = FALSE; // /Should only be whitespace after value.
- }
- }
- if (SMILPriorityClassPauseDisplayInvalid == pPCElement->m_pauseDisplay
- || !bParsedOK)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- cleanup:
- return ret;
- }
- HX_RESULT
- CSmilParser::parseAnchorCoords(const char* pCoords,
- CSmilAnchorElement* pAnchor)
- {
- HX_RESULT rc = HXR_OK;
- INT16 iNumCoords = 0;
- BOOL bIsCircle = FALSE;
- BOOL bIsPoly = FALSE;
- if (0==pAnchor->m_shape.GetLength() ||
- 0==strcmp(pAnchor->m_shape, "rect"))
- {
- iNumCoords = 4;
- }
- else if (0==strcmp(pAnchor->m_shape, "circle"))
- {
- bIsCircle = TRUE;
- iNumCoords = 3;
- }
- // /XXXEH- TODO: handle shape="poly":
- else if (0==strcmp(pAnchor->m_shape, "poly"))
- {
- // /Handles conversion of string to array:
- pAnchor->convertRawPolyData(pCoords);
- bIsPoly = TRUE;
- }
- else
- {
- return HXR_INVALID_PARAMETER;
- }
- if (!bIsPoly)
- {
- double coordArray[4];
- BOOL percentArray[4];
- int i = 0;
- for(i=0; i<4; ++i)
- {
- coordArray[i] = 0.0;
- percentArray[i] = FALSE;
- }
- char* pCoordCopy = new_string(pCoords);
- char* pTok = strtok(pCoordCopy, ",");
- for(i=0;i<iNumCoords,pTok;++i)
- {
- char* pEndPtr = 0;
- double dVal = strtod(pTok, &pEndPtr);
- coordArray[i] = dVal;
- percentArray[i] = (*pEndPtr == '%') ? TRUE: FALSE;
- pTok = strtok(NULL, ",");
- }
- delete[] pCoordCopy;
- pAnchor->m_ulOriginalLeftX = pAnchor->m_ulLeftX =
- (UINT32)coordArray[0];
- pAnchor->m_bLeftXIsPercent = percentArray[0];
- pAnchor->m_ulOriginalTopY = pAnchor->m_ulTopY =
- (UINT32)coordArray[1];
- pAnchor->m_bTopYIsPercent = percentArray[1];
- if (bIsCircle)
- {
- pAnchor->m_ulOriginalRadius = pAnchor->m_ulRadius =
- (UINT32)coordArray[2];
- pAnchor->m_bRadiusIsPercent = percentArray[2];
- }
- else // /Rect:
- {
- pAnchor->m_ulOriginalRightX = pAnchor->m_ulRightX =
- (UINT32)coordArray[2];
- pAnchor->m_bRightXIsPercent = percentArray[2];
- pAnchor->m_ulOriginalBottomY = pAnchor->m_ulBottomY =
- (UINT32)coordArray[3];
- pAnchor->m_bBottomYIsPercent = percentArray[3];
- }
- }
- pAnchor->m_bCoordsSet = TRUE;
- return rc;
- }
- // Functions to parse SMIL Boston Begin & Ends
- HX_RESULT
- CSmilParser::parseBeginEnd(const char* pBuffer,
- CSmilElement* pElement,
- SMILSyncAttributeTag nTag)
- {
- HX_RESULT ret = HXR_OK;
- if (pBuffer == NULL || (nTag != SMILSyncAttrBegin &&
- nTag != SMILSyncAttrEnd))
- {
- HX_ASSERT(FALSE);
- return HXR_FAIL;
- }
- // First we will eat all whitespace.
- const char* pCh = pBuffer;
- while (*pCh && isspace(*pCh))
- {
- ++pCh;
- }
- if (*pCh == ' ')
- {
- // nothing, empty attribute...
- return HXR_OK;
- }
- // /XXXEH- make sure this is not followed by a list of times,
- // which would be an error, e.g., begin="id(foo)(begin); 5s".
- // we need to check for a smil-1.0-syncbase-value && indefinite
- if (strncmp(pCh, "id(", 3) == 0)
- {
- // /XXXEH- TODO: make sure this value gets inserted into the
- // begin|end time list so that any calls to getNextResolvedTimeValue
- // return the correct (and only) value:
- ret = parseSmil1SyncbaseValue(pCh, pElement, nTag);
- // smil-1.0-syncbase-value
- if (SMILSyncAttrEnd == nTag)
- {
- // /This is needed to trick the core into letting the
- // media play when we give it a yet-unresolved end:
- pElement->m_ulDuration = WAY_IN_THE_FUTURE;
- }
- }
- else
- {
- // /If we see "indefinite" in a begin or end list, we need to ignore
- // it if any other begin or end time in the list is valid:
- BOOL bAlreadyHasValidNonIndefiniteValue = FALSE;
- // /Fixes PR 50676(parts 1,2,3 & 4) where element has end=[some event]
- // or end="indefinite" and dur=[some val]; we want to use the dur and
- // ignore the end (for now, if it's an event-based end) in that case:
- if (pElement->m_bHasExplicitDur && !pElement->m_bIndefiniteDuration)
- {
- bAlreadyHasValidNonIndefiniteValue = TRUE;
- }
- // It's a value or value list:
- do
- {
- if (*pCh == ';')
- {
- ++pCh;
- // /SMIL Boston spec says that leading and trailing white-
- // space characters are allowed and should be ignored.
- // e.g., "5s; foo.activateEvent":
- // /Get rid of white space after each ';'
- while (*pCh && isspace(*pCh) )
- {
- ++pCh;
- }
- if (!(*pCh))
- {
- break; // /We've found nothing but spaces after the ;
- }
- }
- SmilTimeValue* pVal = new SmilTimeValue(m_pContext,
- pElement->m_pNode->m_ulTagStartLine, pElement);
- const char* begin = pCh;
- char* buffer = NULL;
- while (*pCh && *pCh != ';')
- {
- ++pCh;
- }
- if (*pCh == ';')
- {
- #if XXXEH
- // /SMIL Boston spec says that leading and trailing white-
- // space characters are allowed and should be ignored.
- // e.g., "5s; foo.activateEvent":
- // /Get rid of white space before each ';'
- const char* pBkCh = pCh-1;
- while (*pBkCh && pBkCh!=begin && isspace(*pBkCh) )
- {
- --pCh;
- --pBkCh;
- }
- #endif
- buffer = new char[pCh - begin + 1];
- strncpy(buffer, begin, pCh - begin); /* Flawfinder: ignore */
- buffer[pCh - begin] = ' ';
- begin = buffer;
- }
- if (strcmp(begin, "indefinite") == 0 &&
- !bAlreadyHasValidNonIndefiniteValue)
- {
- // / "indefinite"
- if (nTag == SMILSyncAttrBegin)
- {
- pElement->m_bIndefiniteBegin = TRUE;
- }
- else if (nTag == SMILSyncAttrEnd)
- {
- pElement->m_bIndefiniteEnd = TRUE;
- pElement->m_bIndefiniteDuration = TRUE;
- }
- }
- else
- {
- ret = pVal->parseValue(begin, nTag,
- (const char*)(pElement->m_pNode->m_id));
- HX_VECTOR_DELETE(buffer); // /Fix mem leak for >1st list times.
- pVal->setTimeOffset(m_tRefTime);
- HX_VECTOR_DELETE(buffer);
- if (SUCCEEDED(ret))
- {
- if (SmilTimeEvent == pVal->m_type)
- {
- pElement->m_bHasAtLeastOneEventBasedBegin = TRUE;
- }
- else
- {
- pElement->m_bHasAtLeastOneNonEventBasedBegin = TRUE;
- }
- if (nTag == SMILSyncAttrBegin)
- {
- // /If time found was a resolved time (i.e., not an
- // event-arc or sync-arc, then reset indefinite-begin
- // flag since we've found another begin time (which
- // means we should now ignore any "indefinite"
- // value(s) already found):
- if (pVal->isTimeResolved())
- {
- pElement->m_bIndefiniteBegin = FALSE;
- bAlreadyHasValidNonIndefiniteValue = TRUE;
- }
- if (!pElement->m_pBeginTimeList)
- {
- pElement->m_pBeginTimeList = new CHXSimpleList;
- }
- pElement->m_pBeginTimeList->AddTail(pVal);
- }
- else // (nTag == SMILSyncAttrEnd)
- {
- // /If time found was a resolved time (i.e., not an
- // event-arc or sync-arc, then reset indefinite-begin
- // flag since we've found another end time (which
- // means we should now ignore any "indefinite"
- // value(s) already found):
- if (pVal->isTimeResolved())
- {
- pElement->m_bIndefiniteEnd = FALSE;
- pElement->m_bIndefiniteDuration = FALSE;
- bAlreadyHasValidNonIndefiniteValue = TRUE;
- }
- if (!pElement->m_pEndTimeList)
- {
- pElement->m_pEndTimeList = new CHXSimpleList;
- }
- pElement->m_pEndTimeList->AddTail(pVal);
- }
- }
- }
- }
- while (SUCCEEDED(ret) && *pCh == ';');
- if (SMILSyncAttrEnd == nTag &&
- !bAlreadyHasValidNonIndefiniteValue)
- {
- // /XXXEH- this is needed to trick the core into letting the
- // media play when we give it an indefinite end:
- pElement->m_ulDuration = WAY_IN_THE_FUTURE;
- }
- if (SUCCEEDED(ret))
- {
- if (nTag == SMILSyncAttrBegin)
- {
- if (FAILED(pElement->setBeginTime(this)))
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorTimeValueNotallowed,
- pBuffer, pElement->m_pNode->m_ulTagStartLine);
- }
- }
- else
- {
- if (FAILED(pElement->setEndTime(this)))
- {
- ret = HXR_FAIL;
- CSmilSMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorTimeValueNotallowed,
- pBuffer, pElement->m_pNode->m_ulTagStartLine);
- }
- }
- }
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::parseRestart(const char* pBuffer,
- CSmilElement* pElement)
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == pBuffer || NULL == pElement)
- {
- ret = HXR_FAILED;
- }
- else if (strcmp(pBuffer, "never") == 0)
- {
- pElement->m_restartBehavior = SmilRestartNever;
- }
- else if (strcmp(pBuffer, "whenNotActive") == 0)
- {
- pElement->m_restartBehavior = SmilRestartWhenNotActive;
- }
- else if (strcmp(pBuffer, "always") == 0)
- {
- pElement->m_restartBehavior = SmilRestartAlways;
- }
- else if (strcmp(pBuffer, "default") == 0)
- {
- pElement->m_restartBehavior =
- pElement->m_restartDefaultBehavior;
- if (SmilRestartInherit == pElement->m_restartBehavior)
- {
- pElement->getParentRestartDefault();
- }
- }
- else
- {
- ret = HXR_FAILED;
- }
- return ret;
- }
- // /XXXEH- TODO: use this in all parseXXX() functions:
- const char*
- CSmilParser::removeSurroundingWhitespace(const char* pValue)
- {
- const char* pRetStr = pValue;
- if (pRetStr)
- {
- while (*pRetStr && isspace(*pRetStr))
- {
- pRetStr++;
- }
- }
- UINT32 ulLen = (UINT32)strlen(pRetStr);
- char* pRetStrEnd = ulLen>0? (char*)(&(pRetStr[ulLen-1])) : NULL;
- if (pRetStrEnd)
- {
- while (pRetStrEnd>pRetStr && *pRetStrEnd &&
- isspace(*pRetStrEnd))
- {
- pRetStrEnd--;
- }
- // /End the string (this may already be ' ', but who cares?):
- *(pRetStrEnd+1) = ' ';
- }
- return pRetStr;
- }
- HX_RESULT
- CSmilParser::parseSensitivity(const char* pValue, CSmilElement* pSource)
- {
- HX_RESULT ret = HXR_OK;
- const char* pWhitespaceRemoved = removeSurroundingWhitespace(pValue);
- if (NULL == pWhitespaceRemoved || NULL == pSource)
- {
- ret = HXR_INVALID_PARAMETER;
- }
- else
- {
- UINT32 ulStrLen = strlen(pWhitespaceRemoved);
- if (strcmp(pWhitespaceRemoved, "opaque") == 0)
- {
- pSource->m_sensitivityToMouseEvents = pWhitespaceRemoved;
- }
- else if (strcmp(pWhitespaceRemoved, "transparent") == 0)
- {
- pSource->m_sensitivityToMouseEvents = pWhitespaceRemoved;
- }
- // /Can't be longer than "+100%" or shorter than "0%":
- else if (ulStrLen <= 5 && ulStrLen >= 2)
- {
- // /Spec "Valid values are non-negative CSS2 percentage values":
- if ('+' == *pWhitespaceRemoved)
- {
- pWhitespaceRemoved++;
- ulStrLen--;
- }
- // /Then, add up the numbers:
- char* pTmp = (char*)pWhitespaceRemoved;
- ULONG32 ulNum = 0;
- BOOL bFoundNumber = FALSE;
- while (*pTmp && (*pTmp>='0' && *pTmp<='9'))
- {
- ulNum *= 10;
- ulNum += *pTmp-'0';
- ++pTmp;
- bFoundNumber=TRUE;
- }
- // /Verify # was found, followed by '%', followed by nothing else:
- if (!bFoundNumber || *pTmp != '%' || *(pTmp+1) != ' ')
- {
- ret = HXR_INVALID_PARAMETER;
- }
- else
- {
- *pTmp = ' ';
- pSource->m_sensitivityToMouseEvents = pWhitespaceRemoved;
- }
- }
- else
- {
- ret = HXR_INVALID_PARAMETER;
- }
- }
- return ret;
- }
- HX_RESULT
- CSmilParser::parseRestartDefault(const char* pBuffer,
- CSmilElement* pElement)
- {
- HX_RESULT ret = HXR_OK;
- if (NULL == pBuffer || NULL == pElement)
- {
- ret = HXR_FAILED;
- }
- else if (strcmp(pBuffer, "never") == 0)
- {
- pElement->m_restartDefaultBehavior = pElement->m_restartBehavior =
- SmilRestartNever;
- }
- else if (strcmp(pBuffer, "whenNotActive") == 0)
- {
- pElement->m_restartDefaultBehavior = pElement->m_restartBehavior =
- SmilRestartWhenNotActive;
- }
- else if (strcmp(pBuffer, "always") == 0)
- {
- pElement->m_restartDefaultBehavior = pElement->m_restartBehavior =
- SmilRestartAlways;
- }
- else if (strcmp(pBuffer, "inherit") == 0)
- {
- pElement->getParentRestartDefault();
- }
- else
- {
- ret = HXR_FAILED;
- }
- return ret;
- }
- FillDefaultType CSmilParser::getFillDefault(CSmilElement* pElement)
- {
- FillDefaultType eFillDefault = FillDefaultAuto;
- if (pElement)
- {
- // Get our fillDefault
- eFillDefault = pElement->m_eFillDefault;
- // If the fillDefault is "inherit", then
- // get our parent's fillDefault
- if (eFillDefault == FillDefaultInherit &&
- pElement->m_pNode && pElement->m_pNode->m_pParent)
- {
- eFillDefault = getFillDefault(pElement->m_pNode->m_pParent->m_pElement);
- }
- }
- return eFillDefault;
- }
- void CSmilParser::resolveFillValue(CSmilElement* pElement)
- {
- if (pElement)
- {
- // Get the tag of this element
- SMILNodeTag eTag = SMILUnknown;
- if (pElement->m_pNode)
- {
- eTag = pElement->m_pNode->m_tag;
- }
- // Resolve based on the parsed fill value.
- // If fill="default", then we resolve based on
- // the value of fillDefault. Also, if fill="transition"
- // and this is a time container, then we ignore
- // the parsed value (which makes it revert to the
- // default of fill="default").
- if (pElement->m_eFill == FillDefault ||
- (pElement->m_eFill == FillTransition &&
- (eTag == SMILPar || eTag == SMILSeq || eTag == SMILExcl)))
- {
- // Resolve the fillDefault attribute
- FillDefaultType eDefault = getFillDefault(pElement);
- // Map this to a fill value
- if (eDefault == FillDefaultRemove)
- {
- pElement->m_eActualFill = FillDefault;
- }
- else if (eDefault == FillDefaultFreeze)
- {
- pElement->m_eActualFill = FillFreeze;
- }
- else if (eDefault == FillDefaultHold)
- {
- pElement->m_eActualFill = FillHold;
- }
- else if (eDefault == FillDefaultTransition)
- {
- pElement->m_eActualFill = FillTransition;
- }
- else if (eDefault == FillDefaultAuto)
- {
- // For fill="auto", we have to determine if either "dur",
- // "end", "repeatCount", or "repeatDur" are specified.
- // If none of these are specified, then we use fill="freeze".
- // Otherwise, it's fill="remove". So initially we assign
- // fill="remove" and then if none of these four are
- // specified, then we replace it with fill="freeze".
- if (isAttributeSpecified(pElement, "dur") ||
- isAttributeSpecified(pElement, "end") ||
- isAttributeSpecified(pElement, "repeatCount") ||
- isAttributeSpecified(pElement, "repeatDur"))
- {
- pElement->m_eActualFill = FillRemove;
- }
- else
- {
- pElement->m_eActualFill = FillFreeze;
- }
- }
- }
- else
- {
- pElement->m_eActualFill = pElement->m_eFill;
- }
- }
- }
- BOOL CSmilParser::isAttributeSpecified(CSmilElement* pElement,
- const char* pszAttr)
- {
- BOOL bRet = FALSE;
- if (pElement &&
- pElement->m_pNode &&
- pElement->m_pNode->m_pValues &&
- pszAttr)
- {
- IHXBuffer* pTmp = NULL;
- HX_RESULT rv = pElement->m_pNode->m_pValues->GetPropertyCString(pszAttr, pTmp);
- if (SUCCEEDED(rv))
- {
- bRet = TRUE;
- }
- HX_RELEASE(pTmp);
- }
- return bRet;
- }
- #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS)
- HX_RESULT CSmilParser::getNextTransitionEnd(CSmilElement* pElement, REF(UINT32) rulTime)
- {
- HX_RESULT retVal = HXR_FAIL;
- if (pElement)
- {
- // Make sure this element has defined start
- // and end times
- if (pElement->m_ulDelay != ((UINT32) -1) &&
- pElement->m_ulDuration != ((UINT32) -1))
- {
- // Get the time we would normally be removed
- // XXXMEH - DELAY_DUR_FIX
- UINT32 ulOurNormalRemoveTime = pElement->m_ulDelay + pElement->m_ulDuration -
- (pElement->m_bBeginOffsetSet ? pElement->m_lBeginOffset : 0);
- UINT32 ulStop = 0;
- HX_RESULT rv = pElement->getCurrentScheduledStopTime(ulStop);
- if (SUCCEEDED(rv))
- {
- ulOurNormalRemoveTime = ulStop;
- }
- // Get the parent of this element
- SMILNode* pParentNode = getSyncAncestor(pElement->m_pNode);
- if (pParentNode)
- {
- // Loop through the children of the parent
- BOOL bFound = FALSE;
- UINT32 ulNextTime = 0;
- SMILNode* pChildNode = pParentNode->getFirstChild();
- while (pChildNode)
- {
- // Get the CSmilElement for this child
- CSmilElement* pChildElement = pChildNode->m_pElement;
- if (pChildElement)
- {
- // Does this child have a begin transition?
- if (pChildElement->m_beginTransition.GetLength() > 0)
- {
- // Is this child scheduled?
- if (pChildElement->m_ulDelay != ((UINT32) -1))
- {
- // Look up the transition
- void* pVoid = NULL;
- if (m_pTransitionMap &&
- m_pTransitionMap->Lookup((const char*) pChildElement->m_beginTransition,
- pVoid) &&
- pVoid)
- {
- // Get the start time of this transition
- UINT32 ulStart = pChildElement->m_ulDelay;
- // Get the ending time of this transition
- CSmilTransition* pTrans = (CSmilTransition*) pVoid;
- UINT32 ulEnd = pChildElement->m_ulDelay +
- pTrans->m_ulDuration;
- // Does this transition start after our
- // normal remove time?
- if (ulStart >= ulOurNormalRemoveTime)
- {
- // We have found a potential transition, so
- // save the minimum time of these potential
- // transition ends
- if (bFound)
- {
- if (ulEnd < ulNextTime)
- {
- ulNextTime = ulEnd;
- }
- }
- else
- {
- bFound = TRUE;
- ulNextTime = ulEnd;
- }
- }
- }
- }
- }
- }
- pChildNode = pParentNode->getNextChild();
- }
- // Did we find any suitable transition end time?
- if (bFound)
- {
- rulTime = ulNextTime;
- retVal = HXR_OK;
- }
- }
- }
- }
- return retVal;
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_TRANSITIONS) */
- void CSmilParser::initParsingMaps()
- {
- UINT32 i = 0;
- // Init the element map
- HX_DELETE(m_pElementMap);
- m_pElementMap = new CHXMapStringToOb();
- if (m_pElementMap)
- {
- SMILElementTable* pTmp = (SMILElementTable*) &g_ElementTable[0];
- while (pTmp && pTmp->m_eElement != NumSMIL2Elements)
- {
- m_pElementMap->SetAt(pTmp->m_pszString,
- (void*) pTmp->m_eElement);
- pTmp++;
- }
- }
- // Alloc the attribute map
- HX_DELETE(m_pAttributeMap);
- m_pAttributeMap = new CHXMapStringToOb();
- if (m_pAttributeMap)
- {
- // Init the SMIL 2 attribute map. This
- // ONLY contains attributes from the SMIL 2 namespace
- SMILAttributeTable* pTmp = (SMILAttributeTable*) &g_AttributeTable[0];
- while (pTmp && pTmp->m_eAttribute != NumSMIL2Attributes)
- {
- m_pAttributeMap->SetAt(pTmp->m_pszString,
- (void*) pTmp->m_eAttribute);
- pTmp++;
- }
- }
- #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
- // Init the RN extension element map
- HX_DELETE(m_pExtElementMap);
- m_pExtElementMap = new CHXMapStringToOb();
- if (m_pExtElementMap)
- {
- SMILElementTable* pTmp = (SMILElementTable*) &g_ExtElementTable[0];
- while (pTmp && pTmp->m_eElement != NumSMIL2Elements)
- {
- m_pExtElementMap->SetAt(pTmp->m_pszString,
- (void*) pTmp->m_eElement);
- pTmp++;
- }
- }
- // Create the attribute type array
- HX_VECTOR_DELETE(m_pAttrType);
- m_pAttrType = new XMLAttributeType [NumSMIL2Attributes];
- if (m_pAttrType)
- {
- // Init the SMIL 2 attribute map. This
- // ONLY contains attributes from the SMIL 2 namespace
- SMILAttributeTable* pTmp = (SMILAttributeTable*) &g_AttributeTable[0];
- while (pTmp && pTmp->m_eAttribute != NumSMIL2Attributes)
- {
- m_pAttrType[pTmp->m_eAttribute] = pTmp->m_eType;
- pTmp++;
- }
- }
- // Alloc the extension attribute map
- HX_DELETE(m_pExtAttributeMap);
- m_pExtAttributeMap = new CHXMapStringToOb();
- if (m_pExtAttributeMap)
- {
- // Init the SMIL 2 extension attribute map. This
- // ONLY contains attributes from the RN extension namespace
- SMILAttributeTable* pTmp = (SMILAttributeTable*) &g_ExtAttributeTable[0];
- while (pTmp && pTmp->m_eAttribute != NumSMIL2Attributes)
- {
- m_pExtAttributeMap->SetAt(pTmp->m_pszString,
- (void*) pTmp->m_eAttribute);
- if (m_pAttrType) m_pAttrType[pTmp->m_eAttribute] = pTmp->m_eType;
- pTmp++;
- }
- }
- // Init the legal attribute map
- HX_DELETE(m_pLegalAttrMap);
- m_pLegalAttrMap = new CRNBinaryMap();
- if (m_pLegalAttrMap)
- {
- HX_RESULT rv = m_pLegalAttrMap->Init(NumSMIL2Elements, NumSMIL2Attributes);
- if (SUCCEEDED(rv))
- {
- BYTE* pVal = (BYTE*) g_LegalAttr;
- BYTE* pLimit = pVal + sizeof(g_LegalAttr);
- while (pVal < pLimit && *pVal != NumSMIL2Elements)
- {
- // First in list is an element
- UINT32 ulElement = *pVal++;
- // Next is the number of attribute collections
- UINT32 ulNumColl = *pVal++;
- // Next is the number of attributes not in collections
- UINT32 ulNumAttr = *pVal++;
- // Process the attribute collections
- for (i = 0; i < ulNumColl; i++)
- {
- UINT32 ulCollectionIndex = *pVal++;
- processCollection(m_pLegalAttrMap, ulElement, ulCollectionIndex);
- }
- // Process the attributes which are not in a collection
- for (i = 0; i < ulNumAttr; i++)
- {
- UINT32 ulAttr = *pVal++;
- m_pLegalAttrMap->Set(ulElement, ulAttr);
- }
- }
- }
- }
- // Init the content model
- HX_DELETE(m_pContentModelMap);
- m_pContentModelMap = new CRNBinaryMap();
- if (m_pContentModelMap)
- {
- HX_RESULT rv = m_pContentModelMap->Init(NumSMIL2Elements, NumSMIL2Elements);
- if (SUCCEEDED(rv))
- {
- BYTE* pVal = (BYTE*) g_LegalContent;
- BYTE* pLimit = pVal + sizeof(g_LegalContent);
- while (pVal < pLimit && *pVal != NumSMIL2Elements)
- {
- // First in list is an element
- UINT32 ulElement = *pVal++;
- // Next is the number of legal elements which
- // can be children of this element
- UINT32 ulNumElements = *pVal++;
- // Process the list of elements
- for (i = 0; i < ulNumElements; i++)
- {
- UINT32 ulLegalContentElement = *pVal++;
- m_pContentModelMap->Set(ulElement, ulLegalContentElement);
- }
- }
- }
- }
- // Init the enumerated attribute map
- deleteEnumAttrMaps();
- m_ppEnumAttrMap = new CHXMapStringToOb* [NumSMIL2Attributes];
- if (m_ppEnumAttrMap)
- {
- // Null out the pointer array
- memset((void*) m_ppEnumAttrMap, 0,
- NumSMIL2Attributes * sizeof(CHXMapStringToOb*));
- // Now run through the enumerated attribute table
- struct EnumAttrTable* pEntry = (struct EnumAttrTable*) g_EnumAttrTable;
- while (pEntry &&
- pEntry->m_eAttr != NumSMIL2Attributes)
- {
- // Get the attribute
- SMIL2Attribute eAttr = pEntry->m_eAttr;
- // Does a map already exist for this attribute?
- if (!m_ppEnumAttrMap[eAttr])
- {
- m_ppEnumAttrMap[eAttr] = new CHXMapStringToOb();
- }
- if (m_ppEnumAttrMap[eAttr])
- {
- // Set the enumerated type string into the map
- m_ppEnumAttrMap[eAttr]->SetAt(pEntry->m_pszStr,
- (void*) pEntry->m_ucEnum);
- }
- pEntry++;
- }
- }
- // Init the required attribute lists
- deleteReqAttrLists();
- m_ppReqAttrList = new CHXSimpleList* [NumSMIL2Elements];
- if (m_ppReqAttrList)
- {
- // Null out the pointer array
- memset((void*) m_ppReqAttrList, 0,
- NumSMIL2Elements * sizeof(CHXSimpleList*));
- // Now run through the required attribute table
- BYTE* pVal = (BYTE*) g_RequiredAttr;
- BYTE* pLimit = pVal + sizeof(g_RequiredAttr);
- while (pVal < pLimit && *pVal != NumSMIL2Elements)
- {
- // Get the element
- UINT32 ulElement = *pVal++;
- // Get the number of required attributes
- UINT32 ulNumReqAttrs = *pVal++;
- // Do we already have a list for this element?
- if (!m_ppReqAttrList[ulElement])
- {
- // We don't already have one, so create one
- m_ppReqAttrList[ulElement] = new CHXSimpleList();
- }
- if (m_ppReqAttrList[ulElement])
- {
- for (UINT32 i = 0; i < ulNumReqAttrs; i++)
- {
- // Get the required attribute
- UINT32 ulAttr = *pVal++;
- // Add it to the list
- m_ppReqAttrList[ulElement]->AddTail((void*) ulAttr);
- }
- }
- }
- }
- // Init the namespace map
- HX_DELETE(m_pNamespaceMap);
- m_pNamespaceMap = new CHXMapStringToOb();
- if (m_pNamespaceMap)
- {
- struct NamespaceTable* pEntry = (struct NamespaceTable*) g_NamespaceTable;
- while (pEntry->m_eNamespace != NamespaceNotImplemented)
- {
- m_pNamespaceMap->SetAt(pEntry->m_pszStr, (void*) pEntry->m_eNamespace);
- pEntry++;
- }
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
- }
- #if defined(HELIX_FEATURE_SMIL2_VALIDATION)
- void CSmilParser::processCollection(CRNBinaryMap* pMap,
- UINT32 ulElement,
- UINT32 ulCollection)
- {
- if (pMap &&
- ulElement < NumSMIL2Elements &&
- ulCollection < NumSMIL2AttributeCollections)
- {
- // Init the parsing variables
- BYTE* pVal = (BYTE*) g_AttrCollections;
- BYTE* pLimit = pVal + sizeof(g_AttrCollections);
- // Find our collection
- while (pVal < pLimit)
- {
- // Get the current collection
- UINT32 ulColl = *pVal++;
- // Get the number of attributes in this collection
- UINT32 ulNumAttr = *pVal++;
- // Is this our collection?
- if (ulColl == ulCollection)
- {
- // This IS our collection, so process it
- for (UINT32 i = 0; i < ulNumAttr; i++)
- {
- // Get the attribute
- UINT32 ulAttr = *pVal++;
- // Set it in the map
- pMap->Set(ulElement, ulAttr);
- }
- // Now we can break out of the loop
- break;
- }
- else
- {
- // Not our collection, so just skip past it
- pVal += ulNumAttr;
- }
- }
- }
- }
- void CSmilParser::deleteEnumAttrMaps()
- {
- if (m_ppEnumAttrMap)
- {
- for (UINT32 i = 0; i < NumSMIL2Attributes; i++)
- {
- HX_DELETE(m_ppEnumAttrMap[i]);
- }
- }
- HX_VECTOR_DELETE(m_ppEnumAttrMap);
- }
- void CSmilParser::deleteReqAttrLists()
- {
- if (m_ppReqAttrList)
- {
- for (UINT32 i = 0; i < NumSMIL2Elements; i++)
- {
- HX_DELETE(m_ppReqAttrList);
- }
- }
- HX_VECTOR_DELETE(m_ppReqAttrList);
- }
- #endif /* #if defined(HELIX_FEATURE_SMIL2_VALIDATION) */
- void CSmilParser::deleteValidationNamespaceList()
- {
- if (m_pValNSList)
- {
- LISTPOSITION pos = m_pValNSList->GetHeadPosition();
- while (pos)
- {
- CNamespaceInfo* pInfo = (CNamespaceInfo*) m_pValNSList->GetNext(pos);
- HX_DELETE(pInfo);
- }
- }
- HX_DELETE(m_pValNSList);
- }
- void CSmilParser::checkForXMMFDependency(CSmilElement* pElement)
- {
- if (pElement->m_bUsesExternalMediaMarkerFile)
- {
- if (!m_pXMMFElementList)
- {
- m_pXMMFElementList = new CHXSimpleList();
- }
- if (m_pXMMFElementList)
- {
- m_pXMMFElementList->AddTail((void*) pElement);
- }
- }
- }
- void CSmilParser::handleAllXMMFReferences()
- {
- if (m_pXMMFElementList)
- {
- LISTPOSITION pos = m_pXMMFElementList->GetHeadPosition();
- while (pos)
- {
- CSmilElement* pElement =
- (CSmilElement*) m_pXMMFElementList->GetNext(pos);
- if (pElement)
- {
- // Handle any external media marker file
- // references in the begin time list
- handleBeginEndListXMMFReferences(pElement,
- pElement->m_pBeginTimeList);
- // Handle any external media marker file
- // references in the end time list
- handleBeginEndListXMMFReferences(pElement,
- pElement->m_pEndTimeList);
- // Handle any external media marker file
- // references in clipBegin
- if (pElement->m_bClipBeginUsesMarker &&
- pElement->m_pszClipBeginExternalMarkerFileName)
- {
- handleClipBeginEndXMMFReference(pElement, TRUE);
- }
- // Handle any external media marker file
- // references in clipEnd
- if (pElement->m_bClipEndUsesMarker &&
- pElement->m_pszClipEndExternalMarkerFileName)
- {
- handleClipBeginEndXMMFReference(pElement, FALSE);
- }
- }
- }
- }
- }
- void CSmilParser::handleBeginEndListXMMFReferences(CSmilElement* pElement,
- CHXSimpleList* pList)
- {
- if (pElement && pList)
- {
- LISTPOSITION pos = pList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pValue = (SmilTimeValue*) pList->GetNext(pos);
- if (pValue &&
- pValue->getTimeType() == SmilTimeMediaMarker &&
- pValue->isExternalMarker())
- {
- // Get the external file name
- const char* pszExtFile = pValue->getExternalMarkerFileName();
- // Get the src that this external
- // file name is relative to
- const char* pszSrc = NULL;
- CSmilElement* pIDElement = findElement(pValue->getIdRef());
- if (pIDElement &&
- pIDElement->m_pNode &&
- (isMediaObject(pIDElement->m_pNode) &&
- pIDElement->m_pNode->m_tag != SMILBrush))
- {
- CSmilSource* pSource = (CSmilSource*) pIDElement;
- if (pSource &&
- pSource->m_src.GetLength() > 0)
- {
- pszSrc = (const char*) pSource->m_src;
- }
- }
- // Handle this external file
- pElement->handleXMMF(pValue->getIdRef(), pszExtFile, pszSrc);
- }
- }
- }
- }
- void CSmilParser::handleClipBeginEndXMMFReference(CSmilElement* pElement,
- BOOL bIsClipBegin)
- {
- if (pElement && pElement->m_pNode)
- {
- // Get the id for this element
- const char* pszID = (const char*) pElement->m_pNode->m_id;
- // Get the src attribute for this element
- const char* pszSrc = NULL;
- if (isMediaObject(pElement->m_pNode) &&
- pElement->m_pNode->m_tag != SMILBrush)
- {
- CSmilSource* pSource = (CSmilSource*) pElement;
- pszSrc = (const char*) pSource->m_src;
- }
- // Get the external file name
- const char* pszExt = (bIsClipBegin ?
- pElement->m_pszClipBeginExternalMarkerFileName :
- pElement->m_pszClipEndExternalMarkerFileName);
- // Now handle the external marker file
- pElement->handleXMMF(pszID, pszExt, pszSrc);
- }
- }
- HX_RESULT CSmilParser::setElementHandler(SMILNode* pNode,
- CSmilElementHandler* pHandler)
- {
- HX_RESULT retVal = HXR_OK;
- if (pNode)
- {
- // Does this node have a CSmilElement?
- if (pNode->m_pElement)
- {
- pNode->m_pElement->m_pHandler = pHandler;
- }
- // Loop through the children and set them as well
- if (pNode->m_pNodeList)
- {
- LISTPOSITION pos = pNode->m_pNodeList->GetHeadPosition();
- while (pos && SUCCEEDED(retVal))
- {
- SMILNode* pChildNode =
- (SMILNode*) pNode->m_pNodeList->GetNext(pos);
- retVal = setElementHandler(pChildNode, pHandler);
- }
- }
- }
- return retVal;
- }
- void CSmilParser::addToBeginOrEndTimeMap(SmilTimeValue* pValue,
- SmilTimingListType eType)
- {
- if (pValue && (eType == SmilBeginTimeList || eType == SmilEndTimeList))
- {
- const char* pszEventName = pValue->getEventName();
- const char* pszElementID = pValue->getIdRef();
- if (pszEventName && pszElementID)
- {
- CHXMapStringToOb* pEventNameMap = NULL;
- if (eType == SmilBeginTimeList)
- {
- if (!m_pBeginTimeMap)
- {
- m_pBeginTimeMap = new CHXMapStringToOb();
- }
- pEventNameMap = m_pBeginTimeMap;
- }
- else
- {
- if (!m_pEndTimeMap)
- {
- m_pEndTimeMap = new CHXMapStringToOb();
- }
- pEventNameMap = m_pEndTimeMap;
- }
- if (pEventNameMap)
- {
- // This is a two-layer map.
- // First layer is a event name lookup
- // Second layer is an element ID lookup
- // The element ID lookup points to a list of SmilTimeValue's.
- //
- // Do we already have an event name entry?
- CHXMapStringToOb* pElementIDMap = NULL;
- void* pVoid = NULL;
- if (!pEventNameMap->Lookup(pszEventName, pVoid))
- {
- // We don't have an event name entry for this event name
- // so first create one
- pElementIDMap = new CHXMapStringToOb();
- // And now stick it in the event name map
- if (pElementIDMap)
- {
- pEventNameMap->SetAt(pszEventName, (void*) pElementIDMap);
- }
- }
- else
- {
- pElementIDMap = (CHXMapStringToOb*) pVoid;
- }
- if (pElementIDMap)
- {
- // Now see if we already have a list for this element ID
- CHXSimpleList* pTimeValueList = NULL;
- pVoid = NULL;
- if (!pElementIDMap->Lookup(pszElementID, pVoid))
- {
- // We don't have a list of time values for
- // that element ID, so create one
- pTimeValueList = new CHXSimpleList();
- // And now stick that list in the map
- if (pTimeValueList)
- {
- pElementIDMap->SetAt(pszElementID, (void*) pTimeValueList);
- }
- }
- else
- {
- pTimeValueList = (CHXSimpleList*) pVoid;
- }
- if (pTimeValueList)
- {
- // Add this SmilTimeValue to the list
- pTimeValueList->AddTail((void*) pValue);
- }
- }
- }
- }
- }
- }
- void CSmilParser::removeFromBeginOrEndTimeMap(SmilTimeValue* pValue,
- SmilTimingListType eType)
- {
- if (pValue && (eType == SmilBeginTimeList || eType == SmilEndTimeList))
- {
- const char* pszEventName = pValue->getEventName();
- const char* pszElementID = pValue->getIdRef();
- if (pszEventName && pszElementID)
- {
- // Get event name map, depending
- // on whether this is a begin or end time value
- CHXMapStringToOb* pEventNameMap = (eType == SmilBeginTimeList ?
- m_pBeginTimeMap : m_pEndTimeMap);
- if (pEventNameMap)
- {
- // Look up element ID map
- void* pVoid1 = NULL;
- if (pEventNameMap->Lookup(pszEventName, pVoid1) && pVoid1)
- {
- // Cast to CHXMapStringToOb
- CHXMapStringToOb* pElementIDMap = (CHXMapStringToOb*) pVoid1;
- // Lookup SmilTimeValue list
- void* pVoid2 = NULL;
- if (pElementIDMap->Lookup(pszElementID, pVoid2) && pVoid2)
- {
- // Cast to CHXSimpleList*
- CHXSimpleList* pTimeValueList = (CHXSimpleList*) pVoid2;
- // Now run through the list to find the value
- LISTPOSITION pos = pTimeValueList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pListValue =
- (SmilTimeValue*) pTimeValueList->GetAt(pos);
- if (pListValue &&
- pListValue == pValue)
- {
- // Remove this entry from the list
- pos = pTimeValueList->RemoveAt(pos);
- }
- else
- {
- // Just go the next one
- pTimeValueList->GetNext(pos);
- }
- }
- }
- }
- }
- }
- }
- }
- BOOL CSmilParser::isTimeValueListPresent(const char* pszEventName,
- const char* pszElementID,
- SmilTimingListType eType,
- REF(CHXSimpleList*) rpList)
- {
- BOOL bRet = FALSE;
- if (pszEventName && pszElementID &&
- (eType == SmilBeginTimeList ||
- eType == SmilEndTimeList))
- {
- // Set default
- rpList = NULL;
- // Get event name map, depending
- // on whether this is a begin or end time value
- CHXMapStringToOb* pEventNameMap = (eType == SmilBeginTimeList ?
- m_pBeginTimeMap : m_pEndTimeMap);
- if (pEventNameMap)
- {
- // Look up element ID map
- void* pVoid1 = NULL;
- if (pEventNameMap->Lookup(pszEventName, pVoid1) && pVoid1)
- {
- // Cast to CHXMapStringToOb
- CHXMapStringToOb* pElementIDMap = (CHXMapStringToOb*) pVoid1;
- // Lookup SmilTimeValue list
- void* pVoid2 = NULL;
- if (pElementIDMap->Lookup(pszElementID, pVoid2) && pVoid2)
- {
- // Cast to CHXSimpleList*
- rpList = (CHXSimpleList*) pVoid2;
- // set return value
- bRet = TRUE;
- }
- }
- }
- }
- return bRet;
- }
- void CSmilParser::clearTimeValueMap(SmilTimingListType eType)
- {
- if (eType == SmilBeginTimeList ||
- eType == SmilEndTimeList)
- {
- CHXMapStringToOb* pEventNameMap = (eType == SmilBeginTimeList ?
- m_pBeginTimeMap : m_pEndTimeMap);
- if (pEventNameMap)
- {
- POSITION pos1 = pEventNameMap->GetStartPosition();
- while (pos1)
- {
- const char* pszKey1 = NULL;
- void* pVoid1 = NULL;
- pEventNameMap->GetNextAssoc(pos1, pszKey1, pVoid1);
- if (pVoid1)
- {
- // Cast to a CHXMapStringToOb
- CHXMapStringToOb* pElementIDMap = (CHXMapStringToOb*) pVoid1;
- // Run through all entries in this map
- POSITION pos2 = pElementIDMap->GetStartPosition();
- while (pos2)
- {
- const char* pszKey2 = NULL;
- void* pVoid2 = NULL;
- pElementIDMap->GetNextAssoc(pos2, pszKey2, pVoid2);
- if (pVoid2)
- {
- // Cast to a CHXSimpleList
- CHXSimpleList* pTimeValueList = (CHXSimpleList*) pVoid2;
- // Now delete it
- HX_DELETE(pTimeValueList);
- }
- }
- }
- }
- }
- if (eType == SmilBeginTimeList)
- {
- HX_DELETE(m_pBeginTimeMap);
- }
- else
- {
- HX_DELETE(m_pEndTimeMap);
- }
- }
- }
- void CSmilParser::checkNodeForExternalEvents(SMILNode* pNode)
- {
- if (pNode)
- {
- // Does this node have a CSmilElement?
- if (pNode->m_pElement)
- {
- // Check its begin time list for custom events
- checkNodeTimeListForExternalEvents(pNode->m_pElement->m_pBeginTimeList);
- // Check its end time list for custom events
- checkNodeTimeListForExternalEvents(pNode->m_pElement->m_pEndTimeList);
- }
- // Recursively check the children of this node
- if (pNode->m_pNodeList)
- {
- LISTPOSITION pos = pNode->m_pNodeList->GetHeadPosition();
- while (pos)
- {
- // Get a child node
- SMILNode* pChildNode = (SMILNode*) pNode->m_pNodeList->GetNext(pos);
- // Check it for custom events
- checkNodeForExternalEvents(pChildNode);
- }
- }
- }
- }
- void CSmilParser::checkNodeTimeListForExternalEvents(CHXSimpleList* pList)
- {
- if (pList)
- {
- LISTPOSITION pos = pList->GetHeadPosition();
- while (pos)
- {
- SmilTimeValue* pTime = (SmilTimeValue*) pList->GetNext(pos);
- if (pTime &&
- pTime->getTimeType() == SmilTimeEvent)
- {
- // Get the event name
- const char* pszEventName = pTime->getEventName();
- // Check whether this is a namespaced event name
- const char* pszEventNameNoPrefix = NULL;
- CNamespaceInfo* pInfo = getNamespaceInfo(pszEventName,
- pszEventNameNoPrefix);
- if (pInfo)
- {
- // This *is* a namespaced event name, so we need
- // to add this custom event to the list
- addExternalEventToList(pTime->getIdRef(),
- pszEventName,
- pszEventNameNoPrefix,
- pInfo);
- }
- }
- }
- }
- }
- void CSmilParser::addExternalEventToList(const char* pszID,
- const char* pszFullName,
- const char* pszName,
- CNamespaceInfo* pInfo)
- {
- if (pszID && pszFullName && pszName && pInfo)
- {
- if (!m_pExternalEventList)
- {
- m_pExternalEventList = new CHXSimpleList();
- }
- if (m_pExternalEventList)
- {
- // First see if this custom event is already present
- BOOL bPresent = FALSE;
- LISTPOSITION pos = m_pExternalEventList->GetHeadPosition();
- while (pos)
- {
- ExternalEventInfo* pListInfo =
- (ExternalEventInfo*) m_pExternalEventList->GetNext(pos);
- if (pListInfo &&
- pListInfo->m_EventBaseID == pszID &&
- pListInfo->m_PrefixedEventName == pszFullName &&
- pListInfo->m_EventName == pszName &&
- pListInfo->m_pInfo == pInfo)
- {
- bPresent = TRUE;
- break;
- }
- }
- // If it's not present, then add it
- if (!bPresent)
- {
- ExternalEventInfo* pNewInfo = new ExternalEventInfo;
- if (pNewInfo)
- {
- // Set the members
- pNewInfo->m_EventBaseID = pszID;
- pNewInfo->m_PrefixedEventName = pszFullName;
- pNewInfo->m_EventName = pszName;
- pNewInfo->m_pInfo = pInfo;
- // Append to the list
- m_pExternalEventList->AddTail((void*) pNewInfo);
- }
- }
- }
- }
- }
- void CSmilParser::clearExternalEventList()
- {
- if (m_pExternalEventList)
- {
- LISTPOSITION pos = m_pExternalEventList->GetHeadPosition();
- while (pos)
- {
- ExternalEventInfo* pInfo =
- (ExternalEventInfo*) m_pExternalEventList->GetNext(pos);
- HX_DELETE(pInfo);
- }
- m_pExternalEventList->RemoveAll();
- }
- }
- void CSmilParser::addStringProperty(IHXValues* pValues,
- IUnknown* pContext,
- const char* pszName,
- const char* pszValue)
- {
- if (pValues && pContext && pszName && pszValue)
- {
- IHXCommonClassFactory* pFact = NULL;
- pContext->QueryInterface(IID_IHXCommonClassFactory, (void**) &pFact);
- if (pFact)
- {
- IHXBuffer* pBuf = NULL;
- pFact->CreateInstance(CLSID_IHXBuffer, (void**) &pBuf);
- if (pBuf)
- {
- HX_RESULT rv = pBuf->Set((const UCHAR*) pszValue, strlen(pszValue) + 1);
- if (SUCCEEDED(rv))
- {
- pValues->SetPropertyCString(pszName, pBuf);
- }
- }
- HX_RELEASE(pBuf);