smlparse.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:137k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: smlparse.cpp,v 1.2.12.2.2.1 2005/01/26 20:10:54 ehyche Exp $
- *
- * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (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.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * 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 ***** */
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include "hxtypes.h"
- #include "hxresult.h"
- #include "hxcom.h"
- #include "hxcomm.h"
- #include "ihxpckts.h"
- #include "hxfiles.h"
- #include "hxformt.h"
- #include "hxengin.h"
- #include "hxplugn.h"
- #include "hxpends.h"
- #include "hxasm.h"
- #include "hxprefs.h"
- #include "hxupgrd.h"
- #include "hxassert.h"
- #include "chxpckts.h"
- #include "upgrdcol.h"
- #include "nptime.h"
- #include "smpte.h"
- #include "debug.h"
- #include "hxstrutl.h"
- #include "hxstring.h"
- #include "cbqueue.h"
- #include "hxslist.h"
- #include "hxurl.h"
- #include "hxmap.h"
- #include "hxstack.h"
- #include "hxwintyp.h"
- #include "chxxtype.h"
- #include "hxparse.h"
- #include "hxxml.h"
- #include "xmlreslt.h"
- #include "looseprs.h"
- #include "hxxmlprs.h" //HXXMLParser
- #include "sm1elem.h"
- #include "sm1time.h"
- #include "sm1error.h"
- #include "sm1parse.h"
- #include "safestring.h"
- #include "hxmon.h"
- #include "debugout.h"
- #include "hxheap.h"
- #ifdef _DEBUG
- #undef HX_THIS_FILE
- static const char HX_THIS_FILE[] = __FILE__;
- #endif
- 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";
- static const struct smil1ColorTable
- {
- char* m_pColorName;
- UINT8 m_ucRed;
- UINT8 m_ucGreen;
- UINT8 m_ucBlue;
- } Smil1ColorTable[] =
- {
- {"black", 0x00, 0x00, 0x00},
- {"silver", 0xc0, 0xc0, 0xc0},
- {"gray", 0x80, 0x80, 0x80},
- {"white", 0xff, 0xff, 0xff},
- {"maroon", 0x80, 0x00, 0x00},
- {"red", 0xff, 0x00, 0x00},
- {"purple", 0x80, 0x00, 0x80},
- {"fuchsia", 0xff, 0x00, 0xff},
- {"green", 0x00, 0x80, 0x00},
- {"lime", 0x00, 0xff, 0x00},
- {"olive", 0x80, 0x80, 0x00},
- {"yellow", 0xff, 0xff, 0x00},
- {"navy", 0x00, 0x00, 0x80},
- {"blue", 0x00, 0x00, 0xff},
- {"teal", 0x00, 0x80, 0x80},
- {"aqua", 0x00, 0xff, 0xff},
- {0, 0x00, 0x00, 0x00}
- };
- static const struct smil1TagTable
- {
- SMIL1NodeTag m_tag;
- const char* m_name;
- } smil1TagTable[] =
- {
- {SMILSmil, "smil"},
- {SMILMeta, "meta"},
- {SMILHead, "head"},
- {SMILBody, "body"},
- {SMILBasicLayout, "layout"},
- {SMILRootLayout, "root-layout"},
- {SMILRegion, "region"},
- {SMILSwitch, "switch"},
- {SMILText, "text"},
- {SMILImg, "img"},
- {SMILRef, "ref"},
- {SMILAudio, "audio"},
- {SMILVideo, "video"},
- {SMILAnimation, "animation"},
- {SMILTextstream, "textstream"},
- {SMILAnchor, "anchor"},
- {SMILAAnchor, "a"},
- {SMILPar, "par"},
- {SMILSeq, "seq"},
- {SMILRNRendererList, RN_TAG_RENDERER_LIST},
- {SMILRendererPreFetch, RN_TAG_RENDERER},
- {SMILUnknown, "unknown"}
- };
- CSmil1Parser::CSmil1Parser(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_bNoNamespaces(FALSE),
- m_bRNNamespace(FALSE),
- m_bIgnoreUnrecognizedElements(TRUE),
- m_bSMILRootLayoutAlreadyFound(FALSE),
- m_bSMIL10FullCompliance(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_pEndLayout(0),
- m_ulBandwidthPreference(0),
- m_ulScreenHeightPreference(0),
- m_ulScreenWidthPreference(0),
- m_ulScreenDepthPreference(0),
- m_pLanguagePreferenceList(0),
- m_bCaptionsPreference(FALSE),
- m_pOverdubOrCaptionPreference(0),
- m_pBasePath(0),
- m_pTagAttributeMap(0),
- m_bContainsSource(FALSE),
- 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_ulPersistentComponentID(0)
- , m_elementWithinTag(WithinUnknown)
- , m_pVarName(NULL)
- , m_ulNextVar(0)
- , m_pTimelineElementManager(NULL)
- {
- if(m_pContext)
- {
- m_pContext->AddRef();
- m_pContext->QueryInterface(IID_IHXCommonClassFactory, (void**)&m_pClassFactory);
- }
- initRequireTags();
- initTagAttributes();
- getPreferences();
- m_pVarName = new char [256];
- m_pTimelineElementManager = new CSmil1TimelineElementManager;
- }
- CSmil1Parser::~CSmil1Parser()
- {
- deleteTagAttributes();
- HX_DELETE(m_pRequireTagsMap);
- 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)
- {
- SMIL1Namespace* pNS = (SMIL1Namespace*)(*ndx);
- HX_DELETE(pNS);
- }
- HX_DELETE(m_pNSConflictList);
- }
- 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
- CSmil1Parser::initRequireTags()
- {
- //XXXBAB - add required tags here
- #if 0
- m_pRequireTagsMap = new CHXMapStringToOb;
- (*m_pRequireTagsMap)["foo-require"] = 0;
- (*m_pRequireTagsMap)["boo-require"] = 0;
- #endif
- }
- void
- CSmil1Parser::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)
- {
- 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 1.0 version) on Mac whose 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);
- }
- if(HXR_OK == pPrefs->ReadPref("screen_depth", pBuf))
- {
- m_ulScreenDepthPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("screen_height", pBuf))
- {
- m_ulScreenHeightPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("screen_width", pBuf))
- {
- m_ulScreenWidthPreference =
- (UINT32)atol((const char*)pBuf->GetBuffer());
- HX_RELEASE(pBuf);
- }
- if(HXR_OK == pPrefs->ReadPref("caption_switch", pBuf))
- {
- m_bCaptionsPreference =
- (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);
- HX_RELEASE(pBuf);
- }
- HX_RELEASE(pPrefs);
- }
- HX_RELEASE(pRegistry);
- }
- void
- CSmil1Parser::close()
- {
- HX_DELETE(m_pPacketQueue);
- HX_DELETE(m_pEndLayout);
- HX_DELETE(m_pTrackHintList);
- HX_RELEASE(m_pResponse);
- HX_RELEASE(m_pErrorText);
- if (m_pParser)
- {
- m_pParser->Close();
- HX_RELEASE(m_pParser);
- }
- HX_RELEASE(m_pISystemRequired);
- if(m_pIDMap)
- {
- CHXMapStringToOb::Iterator i = m_pIDMap->Begin();
- for(; i != m_pIDMap->End(); ++i)
- {
- SMIL1Node* pNode = (SMIL1Node*)(*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)
- {
- CSmil1AddGroup* pAddGroup = (CSmil1AddGroup*)(*i);
- delete pAddGroup;
- }
- HX_DELETE(m_pAddGroupMap);
- }
- if(m_pSourceUpdateList)
- {
- CHXSimpleList::Iterator i = m_pSourceUpdateList->Begin();
- for(; i != m_pSourceUpdateList->End(); ++i)
- {
- CSmil1SourceUpdate* pUpdate = (CSmil1SourceUpdate*)(*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)
- {
- SMIL1Namespace* pNS = (SMIL1Namespace*)(*ndx);
- HX_DELETE(pNS);
- }
- HX_DELETE(m_pNSConflictList);
- }
- delete m_pNodeListStack;
- if(m_pNodeList)
- {
- delete m_pNodeList->m_pParentNode;
- }
- }
- HX_RESULT
- CSmil1Parser::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;
- }
- SMIL1Node* pRootNode = new SMIL1Node;
- pRootNode->m_id = "root";
- pRootNode->m_name = "root";
- m_pNodeList = new SMIL1NodeList;
- pRootNode->m_pNodeList = m_pNodeList;
- m_pNodeList->m_pParentNode = pRootNode;
- m_pNodeListStack->Push(pRootNode);
- #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;
- }
- }
- HX_RELEASE(pFact);
- if (SUCCEEDED(rc))
- {
- m_pResponse = new CSmil1ParserResponse(this);
- m_pResponse->AddRef();
- // Expat is created off the CCF.
- // In strict mode it requires 100% compliant XML. We will
- // create a "loose" version that allows &'s in attribute values.
- // (this parser is still MUCH stricter than the original XML parser)
- rc = m_pParser->Init(m_pResponse, "iso-8859-1", FALSE);
- }
- #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 CSmil1ParserResponse(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
- CSmil1Parser::parse(IHXBuffer* pBuffer, BOOL bIsFinal)
- {
- HX_RESULT rc = HXR_OK;
- rc = m_pParser->Parse(pBuffer, bIsFinal);
- 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
- CSmil1Parser::durationResolved(const char* pID, UINT32 ulDuration)
- {
- SMIL1Node* pNode = NULL;
- IHXBuffer* pBuf = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- if (pNode->m_pElement->m_bIndefiniteDuration)
- {
- goto cleanup;
- }
-
- // add duration to parent element
- if(pNode &&
- pNode->m_pElement &&
- pNode->m_pElement->m_pTimelineElement)
- {
- pNode->m_pElement->m_pTimelineElement->setDuration(ulDuration);
- }
- }
- cleanup:
- HX_RELEASE(pBuf);
- return HXR_OK;
- }
- BOOL AncestorEventsAreResolved(SMIL1Node* pNode)
- {
- if (!pNode || !pNode->m_pElement ||
- !pNode->m_pElement->m_pTimelineElement || pNode->m_tag == SMILBody)
- {
- return TRUE;
- }
- //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()) ||
- (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);
- }
- void
- CSmil1Parser::insertTimelineElement(const char* pID, UINT32 ulDelay)
- {
- SMIL1Node* pNode = 0;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- if(pNode &&
- pNode->m_pElement &&
- !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 or end is dependent on another (not-yet-
- // resolved) element:
- ( (!pNode->m_pElement->m_pTimelineElement->durationEvent() ||
- pNode->m_pElement->m_pTimelineElement->durationSet()) &&
- (!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)
- )
- {
- // /[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_ulBeginOffset != ((UINT32)-1) &&
- pNode->m_pParent->m_pElement->m_ulEndOffset !=
- ((UINT32)-1) &&
- (pNode->m_pElement->m_ulBeginOffset >
- pNode->m_pParent->m_pElement->m_ulEndOffset) )
- {
- return; //Don't insert this because it can't ever play.
- }
- // skip the element if its duration == 0
- if (0 == pNode->m_pElement->m_ulDuration)
- {
- durationResolved(pNode->m_id, 0);
- }
- else
- {
- pNode->m_pElement->m_ulDelay = ulDelay;
- pNode->m_pElement->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
- pNode->m_pElement->m_bInsertedIntoTimeline = TRUE;
- insertElementByTimestamp(pNode->m_pElement);
- }
- }
- }
- }
- void
- CSmil1Parser::resetTimelineElementDuration(const char* pID,
- UINT32 ulDuration)
- {
- SMIL1Node* pNode = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- CSmil1SourceUpdate* pUpdate = new CSmil1SourceUpdate;
- pUpdate->m_ulTimestamp = INITIAL_STREAM1_TIMESTAMP;
- pUpdate->m_srcID = pID;
- pUpdate->m_ulUpdatedDuration = ulDuration;
- if(!m_pSourceUpdateList)
- {
- m_pSourceUpdateList = new CHXSimpleList;
- }
- m_pSourceUpdateList->AddTail(pUpdate);
- insertElementByTimestamp(pUpdate);
- }
- }
- CSmil1Element*
- CSmil1Parser::findElement(const char* pID)
- {
- SMIL1Node* pNode = NULL;
- if(m_pIDMap->Lookup(pID, (void*&)pNode))
- {
- return pNode->m_pElement;
- }
- return NULL;
- }
- const char*
- CSmil1Parser::assignID(const char* pPrefix)
- {
- SafeSprintf(m_pVarName, 256, "%s_%ld", pPrefix, GetUniqueNumber());
- return m_pVarName;
- }
- UINT16
- CSmil1Parser::getFragmentGroup(const char* pFragment)
- {
- if(pFragment)
- {
- SMIL1Node* pNode = 0;
- if(m_pIDMap->Lookup(pFragment, (void*&)pNode))
- {
- if(!pNode->m_bDelete)
- {
- if(pNode->m_tag == SMILAAnchor ||
- pNode->m_tag == SMILSwitch)
- {
- SMIL1Node* pChildNode = getTimelineDescendent(pNode, NULL);
- while(pChildNode)
- {
- if(!pChildNode->m_bDelete)
- {
- return pChildNode->m_nGroup;
- }
- pChildNode = getTimelineDescendent(pNode, pChildNode);
- }
- }
- else if(pNode->m_tag == SMILAnchor)
- {
- SMIL1Node* pParentNode = pNode->m_pParent;
- if(pParentNode &&
- !pParentNode->m_bDelete)
- {
- return pParentNode->m_nGroup;
- }
- }
- else
- {
- return pNode->m_nGroup;
- }
- }
- }
- }
- return 0;
- }
- UINT32
- CSmil1Parser::getFragmentOffset(const char* pFragment,
- //This BOOL will be set to FALSE if the fragment
- // does not exist or does not yet have a resolved
- // begin time. This was necessary to fix PR 22655:
- BOOL& bFragFoundAndResolved)
- {
- bFragFoundAndResolved = FALSE;
- if(pFragment)
- {
- UINT32 ulAnchorBegin = 0;
- SMIL1Node* pNode = NULL;
- CSmil1Element* pElement = NULL;
- CSmil1Element* pActualElement = NULL;
- if(m_pIDMap->Lookup(pFragment, (void*&)pNode) &&
- pNode->m_pElement)
- {
- pElement = pNode->m_pElement;
- if(pNode->m_tag == SMILSwitch ||
- pNode->m_tag == SMILAAnchor)
- {
- SMIL1Node* pChildNode = getTimelineDescendent(
- pNode, NULL);
- while(pChildNode)
- {
- if(!pChildNode->m_bDelete)
- {
- pActualElement = pChildNode->m_pElement;
- break;
- }
- pChildNode = getTimelineDescendent(
- pNode, pChildNode);
- }
- }
- else if(pNode->m_tag == SMILAnchor)
- {
- if(pElement->m_ulBeginOffset != (UINT32)-1)
- {
- ulAnchorBegin = pElement->m_ulBeginOffset;
- }
- SMIL1Node* pParent = pNode->m_pParent;
- if(pParent)
- {
- pActualElement = pParent->m_pElement;
- }
- }
- else
- {
- pActualElement = pElement;
- }
- if(pActualElement)
- {
- //[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(pActualElement->m_ulDelay != (UINT32)-1)
- {
- bFragFoundAndResolved = TRUE;
- return pActualElement->m_ulDelay +
- ulAnchorBegin;
- }
- else if(pActualElement->m_ulBeginOffset != (UINT32)-1)
- {
- bFragFoundAndResolved = TRUE;
- //Changed this while fixing PR 26464:
- // This used to return pActualElement->m_ulDelay +
- // pActualElement->m_ulBeginOffset + ulAnchorBegin 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):
- return pActualElement->m_ulBeginOffset +
- ulAnchorBegin;
- }
- else
- {
- return 0;
- }
- }
- }
- }
- return 0;
- }
- SMIL1Node*
- CSmil1Parser::findFirstNode(SMIL1NodeList* pNodeList, SMIL1NodeTag tag)
- {
- if(!pNodeList)
- {
- return 0;
- }
- SMIL1Node* pFoundNode = 0;
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();i!=pNodeList->End();++i)
- {
- SMIL1Node* pNode = (SMIL1Node*)(*i);
- if(pNode->m_tag == tag)
- {
- pFoundNode = pNode;
- }
- else
- {
- pFoundNode = findFirstNode(pNode->m_pNodeList, tag);
- }
- if(pFoundNode)
- {
- break;
- }
- }
- return pFoundNode;
- }
- SMIL1Node*
- CSmil1Parser::findFirstNode(SMIL1NodeTag tag)
- {
- return findFirstNode(m_pNodeList, tag);
- }
- SMIL1Node*
- CSmil1Parser::getFirstNodeChild(SMIL1Node* pNode)
- {
- m_pCurNode = pNode;
- if(!m_pCurNode)
- {
- return 0;
- }
- return m_pCurNode->getFirstChild();
- }
- SMIL1Node*
- CSmil1Parser::getNextNodeChild()
- {
- if(!m_pCurNode)
- {
- return 0;
- }
- return m_pCurNode->getNextChild();
- }
- HX_RESULT
- CSmil1Parser::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
- CSmil1Parser::parseAnchorCoords(const char* pCoords, CSmil1AnchorElement* pAnchor)
- {
- HX_RESULT rc = HXR_OK;
- 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<4,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];
- 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;
- }
- HX_RESULT
- CSmil1Parser::parseDuration(const char* pDuration, CSmil1Element* pElement,
- SMILSyncAttributeTag nTag)
- {
- HX_RESULT rc = HXR_OK;
- if(!pDuration)
- {
- return HXR_FAIL;
- }
- const char* pCh = pDuration;
- // check for event-source
- // syntax is: id(a)(4s)
- if(strncmp(pCh, "id(", 3) == 0)
- {
- BOOL bParseError = FALSE;
- BOOL bHasEvent = TRUE;
- UINT32 clockValue = 0;
- char* pIdTag = new char[strlen(pDuration)+1];
- char* pEvent = new char[strlen(pDuration)+1];
- pIdTag[0] = 0;
- pEvent[0] = 0;
- pCh += 3; // skip over 'id('
- int i = 0;
- while(*pCh && (*pCh != ')'))
- {
- pIdTag[i++] = *pCh++;
- }
- if(*pCh == ')')
- {
- pIdTag[i] = 0;
- // lookup ID to see if it references an existing entity,
- // otherwise it is an error
- void* pDummy = NULL;
- if(!m_pIDMap->Lookup(pIdTag, pDummy))
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pDuration,
- pElement->m_pNode->m_ulTagStartLine);
- bParseError = TRUE;
- }
- else
- {
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_BeginEventSourceID = pIdTag;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_EndEventSourceID = pIdTag;
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_EndsyncEventSourceID = pIdTag;
- }
- break;
- default:
- break;
- }
- }
- delete[] pIdTag;
- if(strlen(pCh) > 2)
- {
- if(nTag != SMILSyncAttrEndsync)
- {
- pCh++; // skip over ')'
- pCh++; // skip over '('
- i = 0;
- while(*pCh && (*pCh != ')'))
- {
- pEvent[i++] = *pCh++;
- }
- if(*pCh == ')')
- {
- pEvent[i] = 0;
- }
- else
- {
- bParseError = TRUE;
- }
- }
- else
- {
- bParseError = TRUE;
- }
- }
- else
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceID;
- bHasEvent = FALSE;
- }
- else
- {
- bParseError = TRUE;
- }
- }
- }
- else
- {
- bParseError = TRUE;
- }
- if(bParseError)
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pDuration,
- pElement->m_pNode->m_ulTagStartLine);
- }
- else if(bHasEvent)
- {
- SMILEventSourceTag eSourceTag = SMILEventSourceNone;
- UINT32 ulEventClockValue = 0;
- if(strcmp(pEvent, "begin") == 0)
- {
- eSourceTag = SMILEventSourceBegin;
- }
- else if(strcmp(pEvent, "end") == 0)
- {
- eSourceTag = SMILEventSourceEnd;
- }
- else
- {
- if(HXR_OK == parseClockValue(pEvent, ulEventClockValue))
- {
- eSourceTag = SMILEventSourceClock;
- }
- else
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pDuration,
- pElement->m_pNode->m_ulTagStartLine);
- }
- }
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_nBeginEventSourceTag = eSourceTag;
- pElement->m_ulBeginEventClockValue = ulEventClockValue;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_nEndEventSourceTag = eSourceTag;
- pElement->m_ulEndEventClockValue = ulEventClockValue;
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_nEndsyncEventSourceTag = eSourceTag;
- }
- break;
- default:
- break;
- }
- }
- delete[] pEvent;
- }
- else if(strcmp(pCh, "first") == 0)
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceFirst;
- }
- }
- else if(strcmp(pCh, "last") == 0)
- {
- if(nTag == SMILSyncAttrEndsync)
- {
- pElement->m_nEndsyncEventSourceTag = SMILEventSourceLast;
- }
- }
- else if(strcmp(pCh, "indefinite") == 0)
- {
- if (pElement->m_pNode->m_tag == SMILSeq ||
- pElement->m_pNode->m_tag == SMILPar)
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorIndefiniteNotSupported, NULL,
- pElement->m_pNode->m_ulTagStartLine);
- }
- else
- {
- pElement->m_bIndefiniteDuration = TRUE;
- }
- }
- else
- {
- UINT32 ulClockValue = 0;
- if(HXR_OK == parseClockValue(pCh, ulClockValue))
- {
- switch(nTag)
- {
- case SMILSyncAttrBegin:
- {
- pElement->m_ulBeginOffset = ulClockValue;
- }
- break;
- case SMILSyncAttrEnd:
- {
- pElement->m_ulEndOffset = ulClockValue;
- }
- break;
- case SMILSyncAttrDur:
- {
- pElement->m_ulDuration = ulClockValue;
- }
- break;
- case SMILSyncAttrEndsync:
- {
- pElement->m_ulEndSync = ulClockValue;
- }
- break;
- case SMILSyncAttrClipBegin:
- {
- pElement->m_ulClipBegin = ulClockValue;
- }
- break;
- case SMILSyncAttrClipEnd:
- {
- pElement->m_ulClipEnd = ulClockValue;
- }
- break;
-
- default:
- break;
- }
- }
- else
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorBadDuration, pCh,
- pElement->m_pNode->m_ulTagStartLine);
- }
- }
- return rc;
- }
- HX_RESULT
- CSmil1Parser::adjustDuration(CSmil1Element* pElement)
- {
- HX_RESULT rc = HXR_OK;
- // check for duration errors
- if(pElement->m_ulEndOffset != (UINT32)-1)
- {
- if(pElement->m_ulBeginOffset != (UINT32)-1)
- {
- if(pElement->m_ulEndOffset <
- pElement->m_ulBeginOffset)
- {
- pElement->m_ulDuration = 0;
- goto exit;
- }
- if(pElement->m_ulDuration != (UINT32)-1)
- {
- if(pElement->m_ulDuration !=
- pElement->m_ulEndOffset -
- pElement->m_ulBeginOffset)
- {
- // If the element has both an explicit dur and an explicit
- // end, the desired end is the minimum of: the sum of the
- // desired begin and the explicit dur; and the explicit end.
-
- // override "dur"
- if ( pElement->m_ulBeginOffset + pElement->m_ulDuration >
- pElement->m_ulEndOffset )
- {
- // we want to override the duration, because it is
- // greater than the end offset.
- pElement->m_ulDuration =
- pElement->m_ulEndOffset -
- pElement->m_ulBeginOffset;
- }
- else
- {
- // else we want to use the current duration,
- // and override the end offset.
- pElement->m_ulEndOffset = pElement->m_ulBeginOffset
- + pElement->m_ulDuration;
- }
-
- goto exit;
- }
- }
- }
- else
- {
- if(pElement->m_ulDuration != (UINT32)-1)
- {
- if(pElement->m_ulEndOffset >
- pElement->m_ulDuration)
- {
- pElement->m_ulDuration = pElement->m_ulEndOffset;
- goto exit;
- }
- }
- }
- }
-
- // adjust for begin/end/dur attributes
- if(pElement->m_ulDuration == (UINT32)-1) // duration not set
- {
- if(pElement->m_ulEndOffset != (UINT32)-1)
- {
- // has an end but no duration
- if(pElement->m_ulBeginOffset != (UINT32)-1)
- {
- pElement->m_ulDuration = pElement->m_ulEndOffset -
- pElement->m_ulBeginOffset;
- }
- else
- {
- pElement->m_ulDuration = pElement->m_ulEndOffset;
- }
- }
- }
- else // explicit duration set
- {
- if(pElement->m_ulEndOffset != (UINT32)-1)
- {
- // has a duration and an end
- UINT32 ulDur = 0;
- if(pElement->m_ulBeginOffset != (UINT32)-1)
- {
- ulDur = pElement->m_ulEndOffset -
- pElement->m_ulBeginOffset;
- }
- else
- {
- ulDur = pElement->m_ulEndOffset;
- }
- pElement->m_ulDuration = ulDur;
- }
- }
- exit:
- return rc;
- }
- UINT8
- CSmil1Parser::getColorElement(const char* pColorFrag, int len)
- {
- UINT8 ucValue = 0;
- char* pTmpBuf = new char[len+1];
- strncpy(pTmpBuf, pColorFrag, len); /* Flawfinder: ignore */
- pTmpBuf[len] = 0;
- ucValue = (UINT8)strtol(pTmpBuf, 0, 16);
- delete[] pTmpBuf;
- return ucValue;
- }
-
- HXxColor
- CSmil1Parser::parseColor(const char* pColorString)
- {
- HXxColor theColor = 0;
- UINT8 ucRed = 0;
- UINT8 ucGreen = 0;
- UINT8 ucBlue = 0;
- if(pColorString[0] == '#')
- {
- if(strlen(pColorString) == 4)
- {
- /* #rgb, duplicate the numbers */
- char tmpBuf[6]; /* Flawfinder: ignore */
- tmpBuf[0] = tmpBuf[1] = pColorString[1];
- tmpBuf[2] = tmpBuf[3] = pColorString[2];
- tmpBuf[4] = tmpBuf[5] = pColorString[3];
- ucRed = getColorElement(&tmpBuf[0], 2);
- ucGreen = getColorElement(&tmpBuf[2], 2);
- ucBlue = getColorElement(&tmpBuf[4], 2);
- }
- else if(strlen(pColorString) == 7)
- {
- /* #rrggbb */
- ucRed = getColorElement(&pColorString[1], 2);
- ucGreen = getColorElement(&pColorString[3], 2);
- ucBlue = getColorElement(&pColorString[5], 2);
- }
- }
- else
- {
- // string, try to get it from the color table
- int i = 0;
- const char* pColorName = Smil1ColorTable[i].m_pColorName;
- while(pColorName)
- {
- if(strcmp(pColorName, pColorString) == 0)
- {
- ucRed = Smil1ColorTable[i].m_ucRed;
- ucBlue = Smil1ColorTable[i].m_ucBlue;
- ucGreen = Smil1ColorTable[i].m_ucGreen;
- break;
- }
- pColorName = Smil1ColorTable[++i].m_pColorName;
- }
- }
- #ifdef _WINDOWS
- theColor = (HXxColor)(RGB(ucRed, ucGreen, ucBlue));
- #else
- theColor = (HXxColor)
- (ucRed << 16 |
- ucGreen << 8 |
- ucBlue);
- #endif
- return theColor;
- }
- void
- CSmil1Parser::badAttributeError(SMIL1NodeTag tag, const char* pAttrName,
- UINT32 ulLineNumber, BOOL bJustStore)
- {
- const char* pTagName = "unknown";
- // get tag name from table
- int i = 0;
- SMIL1NodeTag thisTag = smil1TagTable[i].m_tag;
- while(thisTag != SMILUnknown)
- {
- if(thisTag == tag)
- {
- pTagName = smil1TagTable[i].m_name;
- break;
- }
- ++i;
- thisTag = smil1TagTable[i].m_tag;
- }
-
- char tmpBuf[256]; /* Flawfinder: ignore */
- SafeSprintf(tmpBuf, 256, "<%s>: %s",
- pTagName, pAttrName);
- if (m_bStoreErrors)
- {
- storeError(SMILErrorUnrecognizedAttribute, tmpBuf, 0,
- ulLineNumber, 0, FALSE);
- }
- if (!bJustStore)
- {
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnrecognizedAttribute, tmpBuf, ulLineNumber);
- }
- }
- CSmil1Meta*
- CSmil1Parser::makeMeta(SMIL1Node* pNode)
- {
- CSmil1Meta* pMeta = new CSmil1Meta(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "name") == 0)
- {
- pMeta->m_name = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "content") == 0)
- {
- pMeta->m_content = (const char*)pBuf->GetBuffer();
- }
- HX_RELEASE(pBuf);
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- HX_RELEASE(pBuf);
- // check for 'base'
- if(pMeta->m_name == "base")
- {
- HX_DELETE(m_pBasePath);
- m_pBasePath = new_string((const char*)pMeta->m_content);
- HX_RELEASE(pBuf);
- }
- }
- return pMeta;
- }
- CSmil1RendererPreFetch*
- CSmil1Parser::makeRendererPreFetch(SMIL1Node* pNode)
- {
- CSmil1RendererPreFetch* pRenderer =
- new CSmil1RendererPreFetch(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "type") == 0)
- {
- pRenderer->m_mimeType = (const char*)pBuf->GetBuffer();
- }
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- return pRenderer;
- }
- CSmil1RootLayout*
- CSmil1Parser::makeRootLayout(SMIL1Node* pNode)
- {
- BOOL bHasHeight = FALSE;
- BOOL bHasWidth = FALSE;
- //[SMIL 1.0 compliance] Fixes PR 22674. SMIL 1.0 documentation states:
- // "If a document contains more than one "root-layout" element,
- // this is an error, and the document should not be displayed."
- if (m_bSMILRootLayoutAlreadyFound && m_bSMIL10FullCompliance)
- {
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorUnexpectedTag,
- (const char*)pNode->m_name, pNode->m_ulTagStartLine);
- return NULL;
- }
- else if (m_bStoreErrors && m_bSMILRootLayoutAlreadyFound)
- {
- storeError(SMILErrorUnexpectedTag, pNode->m_name, 0,
- pNode->m_ulTagStartLine, 0, FALSE);
- }
- m_bSMILRootLayoutAlreadyFound = TRUE;
- CSmil1RootLayout* pLayout = new CSmil1RootLayout(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- //[SMIL 1.0 compliance] Fixes PR 24628. SMIL 1.0
- // documentation states in section 3.3.1 that only "length"
- // values are allowed in a root-layout height or width;
- // percentages are not allowed:
- // [SMIL 1.0 compliance] Also fixes PR 25694: don't allow
- // ANYTHING other than numeric values with 'px' allowed as
- // the only valid units string:
- if (m_bSMIL10FullCompliance)
- {
- if(!strcmp(pName, "height") || !strcmp(pName, "width"))
- {
- const char* pTmp = (const char*)pBuf->GetBuffer();
- UINT32 ulBuflen = pBuf->GetSize();
- UINT32 ulCounter = 0L;
- BOOL bNumCharFound = FALSE;
- BOOL bPxFoundAlready = FALSE;
- while (pTmp && *pTmp)
- {
- //The SMIL 1.0 spec says to use a "length" value as
- // defined in the CSS2 spec, except that the "px"
- // units are optional. The CSS2 spec can be found
- // here:
- // http://www.w3.org/TR/REC-CSS2/syndata.html
- // with the specific definition found here in that
- // page:
- // .../syndata.html#value-def-length
- // Look for: "[+|-](#*)[.][(#*)][px]"
- if (bPxFoundAlready ||
- ( ('0' > *pTmp || '9' < *pTmp) &&
- '.' != *pTmp &&
- (bNumCharFound || ('-' != *pTmp &&
- '+' != *pTmp)) ) )
- {
- //If at least one number was found already
- // and "px" follows, then this char (*pTmp)
- // is not illegal here:
- if (!bPxFoundAlready &&
- bNumCharFound &&
- 'p' == *pTmp &&
- ulCounter < ulBuflen-1 &&
- 'x' == *(pTmp+1) )
- {
- //the first "px" following a number is ok;
- bPxFoundAlready = TRUE;
- ++pTmp; //jump past the 'x'.
- }
- else
- {
- CSmil1SMILSyntaxErrorHandler errHandler(
- m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- (const char*)pBuf->GetBuffer(),
- pNode->m_ulTagStartLine);
- return NULL;
- }
- }
- else if ('.' == *pTmp || '-' == *pTmp ||
- '+' == *pTmp)
- {
- //Valid chars at start, so keep going.
- }
- else
- {
- bNumCharFound = TRUE;
- }
- ++pTmp;
- ++ulCounter;
- }
- }
- }
- if(strcmp(pName, "height") == 0)
- {
- pLayout->m_ulHeight = atol((const char*)pBuf->GetBuffer());
- bHasHeight = TRUE;
- }
- else if(strcmp(pName, "width") == 0)
- {
- pLayout->m_ulWidth = atol((const char*)pBuf->GetBuffer());
- bHasWidth = TRUE;
- }
- else if(strcmp(pName, "background-color") == 0)
- {
- UINT32 ulColor = 0;
- HX_RESULT rv = HXParseColorUINT32((const char*) pBuf->GetBuffer(),
- ulColor);
- if (SUCCEEDED(rv))
- {
- pLayout->m_ulBgColor = ulColor;
- }
- }
- else if(strcmp(pName, "overflow") == 0)
- {
- pLayout->m_overflow = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "title") == 0)
- {
- pLayout->m_title = (const char*)pBuf->GetBuffer();
- }
- else if((strcmp(pName, "id") == 0) ||
- (strcmp(pName, "skip-content") == 0))
- {
- // dont' do anything with these attributes
- }
-
- HX_RELEASE(pBuf);
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- //[SMIL 1.0 Compliance]: PR 24630:
- // height and width are not required in root layout, per the 1.0 spec:
- pLayout->m_bHeightUnspecified = !bHasHeight;
- pLayout->m_bWidthUnspecified = !bHasWidth;
- return pLayout;
- }
- CSmil1Region*
- CSmil1Parser::makeRegion(SMIL1Node* pNode)
- {
- CSmil1Region* pRegion = new CSmil1Region(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- //[SMIL 1.0 compliance] Fixes PR 25697. SMIL 1.0
- // documentation states in section 3.3.1 that only percentage and
- // "length" values are allowed in a root-layout height or width;
- if (m_bSMIL10FullCompliance)
- {
- if(!strcmp(pName, "height") || !strcmp(pName, "width") ||
- !strcmp(pName, "top") || !strcmp(pName, "left"))
- {
- const char* pTmp = (const char*)pBuf->GetBuffer();
- UINT32 ulBuflen = pBuf->GetSize();
- UINT32 ulCounter = 0L;
- BOOL bNumCharFound = FALSE;
- BOOL bPxOrPercentFoundAlready = FALSE;
- while (pTmp && *pTmp)
- {
- //The SMIL 1.0 spec says to use a percentage value
- // or a "length" value as defined in the CSS2 spec,
- // except that the "px" units are the only ones
- // allowed and are optional.
- // The CSS2 spec can be found here:
- // http://www.w3.org/TR/REC-CSS2/syndata.html
- // with the specific definition found here in that
- // page:
- // .../syndata.html#value-def-length
- // Look for: "[+|-](#*)[.][(#*)][px|%]"
- if (bPxOrPercentFoundAlready ||
- ( ('0' > *pTmp || '9' < *pTmp) &&
- '.' != *pTmp &&
- (bNumCharFound || ('-' != *pTmp &&
- '+' != *pTmp)) ) )
- {
- //If at least one number was found already
- // and "px" or "%" follows, then this char
- // (*pTmp) is not illegal here:
- if (!bPxOrPercentFoundAlready &&
- bNumCharFound &&
- ( '%' == *pTmp ||
- ('p' == *pTmp &&
- ulCounter < ulBuflen-1 &&
- 'x' == *(pTmp+1))) )
- {
- //The first "px" or "%" following a number
- // is ok;
- bPxOrPercentFoundAlready = TRUE;
- if ('p' == *pTmp)
- {
- ++pTmp; //jump past the 'x'.
- }
- }
- else
- {
- CSmil1SMILSyntaxErrorHandler errHandler(
- m_pContext);
- errHandler.ReportError(SMILErrorBadAttribute,
- (const char*)pBuf->GetBuffer(),
- pNode->m_ulTagStartLine);
- return NULL;
- }
- }
- else if ('.' == *pTmp || '-' == *pTmp ||
- '+' == *pTmp)
- {
- //Valid chars at start, so keep going.
- }
- else
- {
- bNumCharFound = TRUE;
- }
- ++pTmp;
- ++ulCounter;
- }
- }
- }
- if(strcmp(pName, "left") == 0)
- {
- pRegion->m_left = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "top") == 0)
- {
- pRegion->m_top = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "height") == 0)
- {
- pRegion->m_height = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "width") == 0)
- {
- pRegion->m_width = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "fit") == 0)
- {
- pRegion->m_fit = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "z-index") == 0)
- {
- pRegion->m_zIndex = atol((const char*)pBuf->GetBuffer());
- }
- else if(strcmp(pName, "background-color") == 0)
- {
- const char* pActualColor = (const char*)pBuf->GetBuffer();
- if(strcmp(pActualColor, "transparent") == 0)
- {
- pRegion->m_bBgColorSet = FALSE;
- }
- else
- {
- UINT32 ulColor = 0;
- HX_RESULT rv = HXParseColorUINT32((const char*) pBuf->GetBuffer(),
- ulColor);
- if (SUCCEEDED(rv))
- {
- pRegion->m_ulBgColor = ulColor;
- pRegion->m_bBgColorSet = TRUE;
- }
- }
- }
-
- pBuf->Release();
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- return pRegion;
- }
- CSmil1AAnchorElement*
- CSmil1Parser::makeAAnchorElement(SMIL1Node* pNode)
- {
- CSmil1AAnchorElement* pAnchor =
- new CSmil1AAnchorElement(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "href") == 0)
- {
- pAnchor->m_href = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "show") == 0)
- {
- pAnchor->m_show = (const char*)pBuf->GetBuffer();
- }
- pBuf->Release();
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- return pAnchor;
- }
- CSmil1AnchorElement*
- CSmil1Parser::makeAnchorElement(SMIL1Node* pNode)
- {
- CSmil1AnchorElement* pAnchor = new CSmil1AnchorElement(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- HX_RESULT rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "href") == 0)
- {
- pAnchor->m_href = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "show") == 0)
- {
- pAnchor->m_show = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "coords") == 0)
- {
- rc = parseAnchorCoords((const char*)pBuf->GetBuffer(),
- pAnchor);
- }
- else if(strcmp(pName, "fragment-id") == 0)
- {
- pAnchor->m_fragmentID = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "z-index") == 0)
- {
- pAnchor->m_zIndex = atol((const char*)pBuf->GetBuffer());
- }
- else if(strcmp(pName, "begin") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pAnchor,
- SMILSyncAttrBegin);
- if(HXR_OK == rc)
- {
- pAnchor->m_bTimeValueSet = TRUE;
- }
- }
- else if(strcmp(pName, "end") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pAnchor,
- SMILSyncAttrEnd);
- if(HXR_OK == rc)
- {
- pAnchor->m_bTimeValueSet = TRUE;
- }
- }
- pBuf->Release();
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- return pAnchor;
- }
- CSmil1Source*
- CSmil1Parser::makeSource(SMIL1Node* pNode)
- {
- HX_RESULT rc = HXR_OK;
- CSmil1Source* pSource = new CSmil1Source(pNode);
- // assign to a group
- if(pNode->m_nGroup == (UINT16)-1)
- {
- SMIL1Node* pParent = pNode->m_pParent;
- while(pParent)
- {
- if(pParent->m_nGroup != (UINT16)-1)
- {
- pNode->m_nGroup = pParent->m_nGroup;
- break;
- }
- pParent = pParent->m_pParent;
- }
- }
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "src") == 0)
- {
- CHXString src = (const char*)pBuf->GetBuffer();
-
- // trim leading/trailing spaces
- src.TrimRight();
- src.TrimLeft();
- if(m_pBasePath &&
- isRelativeURL(src))
- {
- pSource->m_src = CHXString(m_pBasePath) + src;
- }
- else
- {
- pSource->m_src = src;
- }
- }
- else if(strcmp(pName, "region") == 0)
- {
- //char szPersistentComponentID[MAX_DISPLAY_NAME] = {0};
- //itoa(m_ulPersistentComponentID, szPersistentComponentID, 10);
-
- // append persistent ID to the end of region id
- // to make it unique in nested meta
- pSource->m_region = (const char*)pBuf->GetBuffer();
- //pSource->m_region += "_";
- //pSource->m_region += szPersistentComponentID;
- }
- else if(strcmp(pName, "begin") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
- SMILSyncAttrBegin);
- }
- else if(strcmp(pName, "end") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
- SMILSyncAttrEnd);
- }
- else if(strcmp(pName, "clip-begin") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
- SMILSyncAttrClipBegin);
- }
- else if(strcmp(pName, "clip-end") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
- SMILSyncAttrClipEnd);
- }
- else if(strcmp(pName, "dur") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pSource,
- SMILSyncAttrDur);
- }
- else if(strcmp(pName, "fill") == 0)
- {
- pSource->m_fill = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "title") == 0)
- {
- pSource->m_title = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "repeat") == 0)
- {
- const char* pRepeatCount = (const char*)pBuf->GetBuffer();
- if(strcmp(pRepeatCount, "indefinite") == 0)
- {
- pSource->m_ulRepeatValue = MAX_UINT32;
- }
- else
- {
- pSource->m_ulRepeatValue = atol(pRepeatCount);
- }
- }
- pBuf->Release();
- if(HXR_OK != rc)
- {
- goto exit;
- }
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- rc = adjustDuration(pSource);
- exit:
- if(HXR_OK != rc)
- {
- HX_DELETE(pSource);
- }
- return pSource;
- }
- CSmil1SeqElement*
- CSmil1Parser::makeSeqElement(SMIL1Node* pNode)
- {
- HX_RESULT rc = HXR_OK;
- CSmil1SeqElement* pElement =
- new CSmil1SeqElement(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "dur") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrDur);
- }
- else if(strcmp(pName, "begin") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrBegin);
- }
- else if(strcmp(pName, "end") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrEnd);
- }
- else if(strcmp(pName, "title") == 0)
- {
- pElement->m_title = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "repeat") == 0)
- {
- pElement->m_ulRepeatValue = atol((const char*)pBuf->GetBuffer());
- }
- pBuf->Release();
- if(HXR_OK != rc)
- {
- goto exit;
- }
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- rc = adjustDuration(pElement);
- exit:
- if(HXR_OK != rc)
- {
- HX_DELETE(pElement);
- }
- return pElement;
- }
- CSmil1ParElement*
- CSmil1Parser::makeParElement(SMIL1Node* pNode)
- {
- HX_RESULT rc = HXR_OK;
- CSmil1ParElement* pElement =
- new CSmil1ParElement(pNode);
- if(pNode->m_pValues)
- {
- const char* pName = 0;
- IHXBuffer* pBuf = 0;
- rc = pNode->m_pValues->GetFirstPropertyCString(pName, pBuf);
- while(HXR_OK == rc)
- {
- if(strcmp(pName, "dur") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrDur);
- }
- else if(strcmp(pName, "begin") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrBegin);
- }
- else if(strcmp(pName, "end") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrEnd);
- }
- else if(strcmp(pName, "endsync") == 0)
- {
- rc = parseDuration((const char*)pBuf->GetBuffer(), pElement,
- SMILSyncAttrEndsync);
- }
- else if(strcmp(pName, "title") == 0)
- {
- pElement->m_title = (const char*)pBuf->GetBuffer();
- }
- else if(strcmp(pName, "repeat") == 0)
- {
- pElement->m_ulRepeatValue = atol((const char*)pBuf->GetBuffer());
- }
- pBuf->Release();
- if(HXR_OK != rc)
- {
- goto exit;
- }
- rc = pNode->m_pValues->GetNextPropertyCString(pName, pBuf);
- }
- }
- rc = adjustDuration(pElement);
- exit:
- if(HXR_OK != rc)
- {
- HX_DELETE(pElement);
- }
- return pElement;
- }
- HX_RESULT
- CSmil1Parser::insertElementByTimestamp(CSmil1Element* pPacket)
- {
- LISTPOSITION lPos = m_pPacketQueue->GetHeadPosition();
- LISTPOSITION lPrev = lPos;
- while(lPos)
- {
- CSmil1Element* pPkt = (CSmil1Element*)m_pPacketQueue->GetNext(lPos);
- if(pPkt->m_ulTimestamp > pPacket->m_ulTimestamp)
- {
- m_pPacketQueue->InsertBefore(lPrev, pPacket);
- return HXR_OK;
- }
- lPrev = lPos;
- }
- m_pPacketQueue->AddTail(pPacket);
- return HXR_OK;
- }
- HX_RESULT
- CSmil1Parser::mapID(SMIL1Node* pNode, BOOL bOverWrite)
- {
- HX_RESULT rc = HXR_OK;
- void* pTmp = 0;
- if(!bOverWrite && m_pIDMap->Lookup((const char*)pNode->m_id, (void*&)pTmp))
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorDuplicateID, pNode->m_id,
- pNode->m_ulTagStartLine);
- }
- else
- {
- (*m_pIDMap)[(const char*)pNode->m_id] = pNode;
- }
- return rc;
- }
- //This function is needed to fix PR 13319. If you have a repeat of greater
- // than 1 in a <seq>, we need a way to map the IDs of the children created
- // when the additional <seq>(s) are created
- HX_RESULT
- CSmil1Parser::mapChildrenIDs(SMIL1NodeList* pNodeList, BOOL bOverWrite)
- {
- HX_RESULT rc = HXR_OK;
- if (!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
- {
- SMIL1Node* pNode = (SMIL1Node*)(*i);
- rc = mapID(pNode, bOverWrite);
- HX_ASSERT(rc == HXR_OK);
- if(pNode->m_pNodeList)
- {
- rc = mapChildrenIDs(pNode->m_pNodeList, bOverWrite);
- }
- }
- return rc;
- }
- HX_RESULT
- CSmil1Parser::markRepeatReplica(SMIL1NodeList* pNodeList, RepeatTag repeatTag)
- {
- HX_RESULT rc = HXR_OK;
- if(!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();rc == HXR_OK && i!=pNodeList->End();++i)
- {
- SMIL1Node* pNode = (SMIL1Node*)(*i);
- pNode->m_repeatTag = repeatTag;
- if(pNode->m_pNodeList)
- {
- rc = markRepeatReplica(pNode->m_pNodeList, repeatTag);
- }
- }
- return rc;
- }
- HX_RESULT
- CSmil1Parser::createElements()
- {
- HX_RESULT rc = HXR_OK;
-
- SMIL1Node* pSMIL1Node = findFirstNode(SMILSmil);
- if(!pSMIL1Node) // dangerwillrobinson!!!
- {
- rc = HXR_FAIL;
- CSmil1SMILSyntaxErrorHandler errHandler(m_pContext);
- errHandler.ReportError(SMILErrorNotSMIL, NULL, 0);
- return rc;
- }
- rc = addToNamespaceScope(pSMIL1Node);
- if (SUCCEEDED(rc))
- {
- // XXXJEFFA Hardcode "cv" namespace prefix for Redstone alpha 7
- rc = addGlobalNamespace((const char*) SYSTEM_COMPONENT_NAMESPACE, "cv");
- }
-
- if (FAILED(rc))
- {
- HX_ASSERT(FALSE);
- return rc;
- }
-
- SMIL1Node* pHeadNode = findFirstNode(SMILHead);
- if(pHeadNode)
- {
- rc = markTestAttributeNodes(pHeadNode->m_pNodeList);
- if (SUCCEEDED(rc))
- {
- rc = addToNamespaceScope(pHeadNode);
- }
- if(SUCCEEDED(rc))
- {
- rc = createHeadElements(pHeadNode->m_pNodeList);
- }
- if (SUCCEEDED(rc))
- {
- rc = removeFromNamespaceScope(pHeadNode);
- }
- }
- if(rc == HXR_OK)
- {
- SMIL1Node* pBodyNode = findFirstNode(SMILBody);
- if(pBodyNode &&
- pBodyNode->m_pNodeList)
- {
- rc = addToNamespaceScope(pBodyNode);
- if (SUCCEEDED(rc))
- {
- SMIL1Node* pTopNode = getTimelineDescendent(pBodyNode, NULL);
- if(pTopNode &&
- pTopNode->m_tag != SMILSeq)
- {
- createSeqWrapper(pBodyNode->m_pNodeList);
- }
- //[SMIL 1.0 compliance] fix for PR 23050:
- // if first descendent of body is a <switch> and its first child
- // is a <seq> that did not get chosen in the switch, then we
- // would be tricked into thinking we already had a valid outer
- // seq, but we wouldn't. Let's put one there in this case,
- // noting that we don't yet know if that seq is valid or not.
- // However, it doesn't matter either way:
- if(pTopNode && SMILSeq == pTopNode->m_tag &&
- pTopNode->m_pParent &&
- pTopNode->m_pParent->m_tag == SMILSwitch)
- {
- createSeqWrapper(pBodyNode->m_pNodeList);
- }
-
- if(HXR_OK != markTestAttributeNodes(pBodyNode->m_pNodeList) ||
- HXR_OK != expandRepeatElements(pBodyNode->m_pNodeList) ||
- HXR_OK != createBodyElements(pBodyNode->m_pNodeList) ||
- HXR_OK != assignGroupIndexes(pBodyNode->m_pNodeList) ||
- HXR_OK != constructTimelineElements(pBodyNode->m_pNodeList) ||
- HXR_OK != setInitialDelays(pBodyNode->m_pNodeList) ||
- // HXR_OK != updateEventElements(pBodyNode->m_pNodeList) ||
- #ifdef _DEBUG
- HXR_OK != printBodyElements(pBodyNode->m_pNodeList) ||
- #endif
- HXR_OK != insertGroups())
- {
- rc = HXR_FAIL;
- }
- }
- if (SUCCEEDED(rc))
- {
- rc = removeFromNamespaceScope(pBodyNode);
- }
- }
- if(rc == HXR_OK && !m_bContainsSource)
- {
- rc = HXR_OK;
- //[SMIL 1.0 compliance] fixes PR 27672:
- // don't call SMILErrorNoBodyElements error as it is not one
- // per the SMIL 1.0 spec.
- }
- }
- return rc;
- }
- HX_RESULT
- CSmil1Parser::createSeqWrapper(SMIL1NodeList* pNodeList)
- {
- // create a default <seq></seq> wrapper within the <body></body>
- HX_RESULT rc = HXR_OK;
- SMIL1Node* pSeqNode = new SMIL1Node;
- pSeqNode->m_name = "seq";
- pSeqNode->m_pParent = pNodeList->m_pParentNode;
- pSeqNode->m_id = assignID("seq");
- pSeqNode->m_tag = SMILSeq;
- pSeqNode->m_pNodeList = new SMIL1NodeList;
- // Must put the node in the id map - otherwise
- // we leak the node
- mapID(pSeqNode, TRUE);
- // move children from bodyNode list to seq list
- int count = pNodeList->GetCount();
- SMIL1Node* pEndBodyNode = NULL;
- while( count > 0) // don't reparent </body> tag
- {
- SMIL1Node* pChildNode = (SMIL1Node*)pNodeList->RemoveHead();
- //XXXJHUG don't reparent the </body> tag...
- if ( pChildNode->m_id != "CLOSE-body" )
- {
- pChildNode->m_pParent = pSeqNode;
- pSeqNode->m_pNodeList->AddTail(pChildNode);
- }
- else
- {
- pEndBodyNode = pChildNode;
- }
- --count;
- }
- SMIL1Node* pEndSeqNode = new SMIL1Node;
- pEndSeqNode->m_name = "seq";
- pEndSeqNode->m_id = "CLOSE-seq";
- pEndSeqNode->m_pParent = pSeqNode;
- pEndSeqNode->m_tag = SMILEndSeq;
- pSeqNode->m_pNodeList->AddTail(pEndSeqNode);
- // now add it to the <body> parent...
- pNodeList->AddHead(pSeqNode);
- pNodeList->AddTail(pEndBodyNode);
- return rc;
- }
- #if 0
- //XXXBAB - useful for debugging
- void
- CSmil1Parser::PrintNode(SMIL1Node* pNode, FILE* fp, int level)
- {
- for(int tab=0;tab<level;++tab)
- {
- fprintf(fp, "t");
- }
- fprintf(fp, "%sn", (const char*)pNode->m_id);
- if(pNode->m_pNodeList)
- {
- CHXSimpleList::Iterator i = pNode->m_pNodeList->Begin();
- for(; i != pNode->m_pNodeList->End(); ++i)
- {
- SMIL1Node* pChildNode = (SMIL1Node*)(*i);
- PrintNode(pChildNode, fp, level+1);
- }
- }
- }
- void
- CSmil1Parser::PrintNodes()
- {
- FILE* fp = fopen("nodes.txt", "w");
- SMIL1Node* pNode = (SMIL1Node*)m_pNodeList->GetHead();
- PrintNode(pNode, fp, 0);
- fclose(fp);
- }
- #endif
- HX_RESULT
- CSmil1Parser::printBodyElements(SMIL1NodeList* pNodeList)
- {
- // debugging code...
- HX_RESULT rc = HXR_OK;
- //#define XXXEH_FOR_DEBUGGING_ONLY
- #if defined(XXXEH_FOR_DEBUGGING_ONLY)
- static int level = 0;
- if(!pNodeList)
- {
- return rc;
- }
- CHXSimpleList::Iterator i;
- for(i=pNodeList->Begin();i!=pNodeList->End();++i)
- {
- if(HXR_OK != rc)
- {
- return rc;
- }
- SMIL1Node* pNode = (SMIL1Node*)(*i);
- FILE* fp=fopen("c:\temp\smil.txt", "a+");
- if (!fp)
- {
- break;
- }
- for(int i=0;i<level;++i)
- {
- fprintf(fp, "t");
- }
- UINT32 ulDelay = (UINT32)-1;
- if(pNode->m_pElement &&
- pNode->m_pElement->m_pTimelineElement)
- {
- ulDelay = pNode->m_pElement->m_pTimelineElement->getDelay();
- }
- fprintf(fp, "%s tag %d group %d repeatid %s delay %d deleted %dn", (const char*)pNode->m_id,
- pNode->m_tag, pNode->m_nGroup, (const char*)pNode->m_repeatid, ulDelay, pNode->m_bDelete);
- fclose(fp);
- if(pNode->m_pNodeList)
- {
- ++level;
- rc = printBodyElements(pNode->m_pNodeList);
- --level;
- }
- }
- #endif
- return rc;
- }
- HX_RESULT
- CSmil1Parser::insertGroups()
- {
- HX_RESULT rc = HXR_OK;
- if(!m_pAddGroupMap)
- {
- rc = HXR_UNEXPECTED;
- }
- else
- {
- UINT32 ulGroupNo = 0;
- CSmil1AddGroup* pAddGroup = 0;
- BOOL bGroupInserted = FALSE;
- while(m_pAddGroupMap->Lookup(ulGroupNo++, (void*&)pAddGroup))
- {
- bGroupInserted = TRUE;
- pAddGroup->m_ulDelay = 0;
- pAddGroup->m_ulTimestamp = INITIAL_STREAM0_TIMESTAMP;
- insertElementByTimestamp(pAddGroup);
- }
- }
- return rc;
- }
- BOOL
- CSmil1Parser::inLanguagePreference(const char* pLang)
- {
- // return FALSE if language preference is not in m_pLanguagePreferenceList
- BOOL rc = FALSE;
- // pLang can be comma separated lists,
- // with '*' accepting all languages
- // copy the string so strtok doesn't modify something bad...
- char* pLangCopy = new_string(pLang);
- char* pLangFrag = strtok(pLangCopy, ",");
- while(pLangFrag)
- {
- if(*pLangFrag == '*') // wildcard
- {
- rc = TRUE;
- break;
- }
- // copy the primary tag part of the language (up to '-')
- char* pPrimaryTag = new char[strlen(pLang)+1];
- char* pTagPtr = pPrimaryTag;
- char* pFragPtr = pLangFrag;
- while(*pFragPtr && *pFragPtr != '-')
- {
- *pTagPtr++ = *pFragPtr++;
- }
- *pTagPtr = ' ';
- CHXSimpleList::Iterator i = m_pLanguagePreferenceList->Begin();
- for(; i != m_pLanguagePreferenceList->End(); ++i)
- {
- char* pPrefLang = (char*)(*i);
- if(*pPrefLang == '*') // wildcard
- {
- rc = TRUE;
- }
- else if(strcmp(pPrefLang, pLangFrag) == 0)
- {
- rc = TRUE;
- }
- else if(strncmp(pPrefLang, pPrimaryTag, strlen(pPrimaryTag)) == 0)
- {
- rc = TRUE;
- }
- if(rc)
- {
- break;
- }
- }
- delete[] pPrimaryTag;
- if(rc)
- {
- break;
- }
- pLangFrag = strtok(NULL, ",");
- }
- delete[] pLangCopy;
- return rc;
- }
- BOOL
- CSmil1Parser::systemComponentFailed(IHXBuffer* pRequiredValue)
- {
- BOOL bFailed = TRUE;
- IHXUpgradeCollection* pUpgradeCollection = new HXUpgradeCollection;
- pUpgradeCollection->AddRef();
- pUpgradeCollection->Add(eUT_Required, pRequiredValue, 0, 0);
- if (m_pISystemRequired == NULL)
- {
- m_pContext->QueryInterface(IID_IHXSystemRequired,
- (void**)&m_pISystemRequired);
- }
- // there may not be a system required interface
- if (m_pISystemRequired != NULL)
- {
- bFailed = FAILED(m_pISystemRequired->HasFeatures(pUpgradeCollection));
- }
- HX_RELEASE(pUpgradeCollection);
- return bFailed;
- }
- BOOL
- CSmil1Parser::testAttributeFailed(SMIL1Node* pNode)
- {
- HX_RESULT rc = HXR_OK;
- BOOL bFailed = FALSE;
- IHXBuffer* pBuf = 0;
- if(pNode->m_pValues)
- {
- rc = pNode->m_pValues->GetPropertyCString("system-required", pBuf);
- if(HXR_OK == rc)
- {
- const char* pActualString = (const char*)pBuf->GetBuffer();
- // Check with the core first
-
- if(m_pRequireTagsMap)
- {
- void* pTag = 0;
- if(!m_pRequireTagsMap->Lookup(pActualString,
- (void*&) pTag))
- {
- bFailed = TRUE;
- }
- }
- else // no required list, can't parse it
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("system-bitrate", pBuf);
- if(HXR_OK == rc)
- {
- UINT32 ulBandwidth = atol((const char*)pBuf->GetBuffer());
- if(m_ulBandwidthPreference < ulBandwidth)
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("system-language", pBuf);
- if(HXR_OK == rc)
- {
- if(m_pLanguagePreferenceList)
- {
- const char* pLang = (const char*)pBuf->GetBuffer();
- if(!inLanguagePreference(pLang))
- {
- bFailed = TRUE;
- }
- }
- else // no preference, can't do it...
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString("system-captions", pBuf);
- if(HXR_OK == rc)
- {
- const char* pActualValue = (const char*)pBuf->GetBuffer();
- if(strcmp(pActualValue, "on") == 0)
- {
- if(!m_bCaptionsPreference)
- {
- bFailed = TRUE;
- }
- }
- else
- {
- if(m_bCaptionsPreference)
- {
- bFailed = TRUE;
- }
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- if(HXR_OK == pNode->m_pValues->GetPropertyCString(
- "system-overdub-or-caption", pBuf))
- {
- if(m_pOverdubOrCaptionPreference)
- {
- const char* pActualValue = (const char*)pBuf->GetBuffer();
- if(strcmp(pActualValue, "caption") == 0)
- {
- if(strcmp(m_pOverdubOrCaptionPreference, "caption") != 0)
- {
- bFailed = TRUE;
- }
- }
- else if(strcmp(pActualValue, "overdub") == 0)
- {
- if(strcmp(m_pOverdubOrCaptionPreference, "overdub") != 0)
- {
- bFailed = TRUE;
- }
- }
- }
- else
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString(
- "system-screen-size", pBuf);
- if(HXR_OK == rc)
- {
- UINT32 ulScreenHeight = 0;
- UINT32 ulScreenWidth = 0;
- const char* pScreenSize = (const char*)pBuf->GetBuffer();
- // format is screen-height "X" screen-width
- char tmp[256]; /* Flawfinder: ignore */
- SafeStrCpy(tmp, pScreenSize, 256);
- char* pScreenHeight = strtok(tmp, "X");
- if(pScreenHeight)
- {
- ulScreenHeight = atol(pScreenHeight);
- char* pScreenWidth = strtok(NULL, "");
- if(pScreenWidth)
- {
- ulScreenWidth = atol(pScreenWidth);
- }
- }
- if((m_ulScreenHeightPreference < ulScreenHeight) ||
- (m_ulScreenWidthPreference < ulScreenWidth))
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- rc = pNode->m_pValues->GetPropertyCString(
- "system-screen-depth", pBuf);
- if(HXR_OK == rc)
- {
- UINT32 ulScreenDepth = atol((const char*)pBuf->GetBuffer());
- if(m_ulScreenDepthPreference < ulScreenDepth)
- {
- bFailed = TRUE;
- }
- pBuf->Release();
- if(bFailed)
- {
- goto exit;
- }
- }
- if (m_pActiveNamespaceMap)
- {
- // look through name spaces for systemComponent name space. If it's there
- // append the prefix and look for systemComponent test attribute
- CHXMapStringToOb::Iterator ndxBuffer = m_pActiveNamespaceMap->Begin();
- for (; ndxBuffer != m_pActiveNamespaceMap->End(); ++ndxBuffer)
- {
- IHXBuffer* pBuffer = (IHXBuffer*)(*ndxBuffer);
- if (strcmp((const char*) SYSTEM_COMPONENT_NAMESPACE, (const char*)pBuffer->GetBuffer()) == 0)
- {
- const char* pPrefix = (const char*)ndxBuffer.get_key();
- // +1 for the : in the namespace and 1 for the