hxsrc.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:69k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxsrc.cpp,v 1.35.2.1 2004/07/09 02:05:58 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxtypes.h"
  50. #include "hxcom.h"
  51. #ifdef _WINDOWS
  52. #include <windows.h>
  53. #endif
  54. #include "hlxclib/stdio.h"
  55. #include "hlxclib/stdlib.h"
  56. #include "prefdefs.h"
  57. #include "plprefk.h"
  58. #include "hxcomm.h"
  59. #include "ihxpckts.h"
  60. #include "hxfiles.h"
  61. #include "hxengin.h"
  62. #include "hxcore.h"
  63. #include "hxprefs.h"
  64. #include "hxpref.h"
  65. #include "hxausvc.h"
  66. #include "hxmon.h"
  67. #include "hxclreg.h"
  68. #include "hxgroup.h"
  69. #include "hxsmbw.h"
  70. #include "hxstrm.h"
  71. #include "hxwin.h"
  72. #include "hxcore.h"
  73. #include "hxhyper.h"
  74. #include "playhpnv.h"
  75. #include "hxplugn.h"
  76. #include "hxrendr.h"
  77. #include "chxeven.h"
  78. #include "chxelst.h"
  79. #include "hxmap.h"
  80. #include "hxrquest.h"
  81. #include "hxmangle.h"
  82. #include "hxtick.h"
  83. #include "dbcs.h"
  84. #include "hxstrutl.h"
  85. #include "strminfo.h"
  86. #include "timeval.h"
  87. #include "statsmgr.h"
  88. #include "hxbsrc.h"
  89. #include "hxsrc.h"
  90. #include "srcinfo.h"
  91. #include "corshare.h"
  92. #include "upgrdcol.h"
  93. #include "hxrasyn.h"
  94. #include "hxaudstr.h"
  95. #include "hxplugn.h"
  96. #include "hxrendr.h"
  97. #include "errdbg.h"
  98. // will be taken out once flags are defined in a separate file
  99. #include "rmfftype.h"
  100. #include "hxplay.h"
  101. #include "hxcleng.h"
  102. #include "hxsrc.h"
  103. #include "hxheap.h"
  104. #ifdef _DEBUG
  105. #undef HX_THIS_FILE
  106. static const char HX_THIS_FILE[] = __FILE__;
  107. #endif
  108. #if defined(HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES)
  109. // TurboPlay should never be turned on in low heap mode, but just in case ...
  110. #define TURBO_AUDIO_PUSHDOWN 100
  111. #else
  112. #define TURBO_AUDIO_PUSHDOWN 2000
  113. #endif
  114. HXSource::HXSource() :
  115.   m_pPlayer (0)
  116. , m_lRefCount(0)
  117. , m_ulStreamIndex(0)
  118. , m_bInitialized (FALSE)
  119. , m_bIsPreBufferingDone(FALSE)
  120. , m_bClipTimeAdjusted(FALSE)
  121. , mLastError (HXR_OK)
  122. , m_ulPerfectPlayTime (0)
  123. , m_ulBufferedPlayTime(0)
  124.         , m_ulStreamHeadersExpected(0)
  125. , m_bPerfectPlayEntireClip(FALSE)
  126. , m_bCannotBufferEntireClip(FALSE)
  127. , m_uNumStreams (0)
  128. , mFlags (0)
  129. , m_bPerfectPlayAllowed (FALSE)
  130. , mSaveAsAllowed (FALSE)
  131. , mLiveStream (FALSE)
  132. , m_bRestrictedLiveStream (FALSE)
  133. , m_bSourceEnd (FALSE)
  134. , m_bForcedSourceEnd(FALSE)
  135. , m_ulPreRollInMs (0)
  136. , m_ulPreRoll (0)
  137. , m_ulAvgBandwidth (0)
  138. , m_ulDuration (0)
  139. , m_bReceivedData (FALSE)
  140. , m_bReceivedHeader(FALSE)
  141. , m_bNonSeekable(FALSE)
  142. , m_nSeeking (0)
  143. , m_bPaused (FALSE)  
  144. , m_bFirstResume(TRUE)
  145. , m_bResumePending(FALSE)
  146. , m_bIsActive(FALSE)
  147. , m_uActiveStreams (0)
  148. , m_pszURL(NULL)
  149. , m_pURL(NULL)
  150. , m_bAltURL(TRUE)
  151. , m_ulStartTime (0)
  152. , m_ulEndTime (0)
  153. , m_ulDelay (0)
  154. , m_ulOriginalDelay (0)
  155. , m_ulPrefetchDelay (0)
  156. , m_llLastExpectedPacketTime(0)
  157. , m_ulRestrictedDuration(0)
  158. , m_bDelayed(FALSE)
  159. , m_ulSourceStartTime(0)
  160. , m_pPreferences (0)
  161. , m_pRegistry (0)
  162. , m_pScheduler (0)
  163. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  164. , m_pStats (0)
  165. , m_pStatsManager(NULL)
  166. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  167. , m_bLocked (FALSE)
  168. , m_pEngine (0)
  169. , m_bRebufferingRequired(FALSE)
  170. , m_bInitialBuffering(TRUE)
  171. , m_bPartOfNextGroup(FALSE)
  172. , m_bPartOfPrefetchGroup(FALSE)
  173. , m_pBufferManager(NULL)
  174. , m_pFileHeader(0)
  175. , m_bPerfectPlay(FALSE)
  176. , m_bBufferedPlay(FALSE)
  177. , m_ulLossHack(0)
  178. , m_ulNumFakeLostPackets(0)
  179. , m_ulLastBufferingCalcTime(0)
  180. , m_pSourceInfo(NULL)
  181. , m_pRequest(NULL)
  182. , m_pASMSource(NULL)
  183. , m_pBackChannel(NULL)
  184. , m_bDefaultAltURL(FALSE)
  185. , m_bCustomEndTime(FALSE)
  186. , m_bCustomDuration(FALSE)
  187. , m_bIsPreBufferingStarted(FALSE)
  188. , m_ulOriginalDuration(0)
  189. , m_bReSetup(FALSE)
  190. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  191. , m_pUpgradeCollection(NULL)
  192. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  193. , m_bRTSPRuleFlagWorkAround(FALSE)
  194.         , m_bContinueWithHeaders(FALSE)
  195. , m_bPrefetch(FALSE)
  196. , m_prefetchType(PrefetchUnknown)
  197. , m_ulPrefetchValue(0)
  198. , m_ulFirstPacketTime(0)
  199. , m_bIsMeta(FALSE)
  200. , m_bFastStart(FALSE)
  201. , m_serverTurboPlay(TURBO_PLAY_UNKNOWN)
  202. , m_ulMaxBandwidth(4000) // 4000kbps
  203. , m_pAudioStreamList(NULL)
  204.         , m_maxPossibleAccelRatio(4.0) // I donno what's a good value?
  205.         , m_ulTurboPushDown(TURBO_AUDIO_PUSHDOWN)
  206.         , m_bSureStreamClip(FALSE)
  207.         , m_ulTurboStartActiveTime(0)
  208. , m_srcEndCode(END_UNKNOWN)
  209. , m_pRecordControl(NULL)
  210. , m_bPlayFromRecordControl(FALSE)
  211.         , m_pRedirectURL(NULL)
  212.         , m_bRedirectPending(FALSE)
  213. {
  214.     mStreamInfoTable = new CHXMapLongToObj;
  215. }
  216. HXSource::~HXSource()
  217. {
  218.     // XXX moved this to the distuctor because we want to keep arround
  219.     // the request until the renderers are close at which point we should
  220.     // be released and deleted.
  221.     HX_RELEASE(m_pRequest);
  222.     HX_VECTOR_DELETE(m_pszURL);
  223.     HX_DELETE(mStreamInfoTable);
  224. }
  225. void
  226. HXSource::Stop()
  227. {
  228.     m_pSourceInfo = NULL;    
  229.     HX_DELETE (m_pURL);
  230.     HX_DELETE (m_pBufferManager);
  231.     if ( FAILED(mLastError) )
  232.     {
  233. HX_RELEASE(m_pRequest);
  234.     }
  235. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  236.     if (m_pStatsManager)
  237.     {
  238. m_pStatsManager->DoCleanup();
  239. HX_RELEASE(m_pStatsManager);
  240.     }        
  241.     HX_DELETE(m_pStats);    
  242. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  243.     DeleteAllEvents(); 
  244.     HX_RELEASE(m_pRegistry);
  245.     HX_RELEASE(m_pPreferences);
  246.     HX_RELEASE(m_pScheduler);
  247.     HX_RELEASE(m_pEngine);
  248. }    
  249. HX_RESULT HXSource::DoCleanup(EndCode endCode)
  250. {
  251.     m_ulDuration = 0;    
  252.     m_ulPreRollInMs = 0;
  253.     m_ulPreRoll = 0;
  254.     m_ulAvgBandwidth = 0;
  255.     m_ulLastBufferingCalcTime = 0;
  256.     m_ulMaxBandwidth = 0;
  257.     m_serverTurboPlay = TURBO_PLAY_UNKNOWN;
  258.     m_bAltURL = FALSE;    
  259.     m_bPaused = FALSE;
  260.     m_bFirstResume = TRUE;
  261.     m_bIsActive = FALSE;
  262.     m_bResumePending = FALSE;
  263.     m_bIsPreBufferingStarted = FALSE;
  264.     m_bIsPreBufferingDone = FALSE;    
  265.     m_bClipTimeAdjusted = FALSE;    
  266.     m_bInitialBuffering = TRUE;
  267.     m_bRebufferingRequired = FALSE;    
  268.     m_bReceivedData = FALSE;
  269.     m_bReceivedHeader = FALSE;
  270.     ReleaseAudioStreams(m_pAudioStreamList);
  271.     HX_DELETE(m_pAudioStreamList);
  272.     DeleteStreamTable();
  273.     CHXSimpleList::Iterator lIter = m_HXStreamList.Begin();
  274.     for (; lIter != m_HXStreamList.End(); ++lIter)
  275.     {
  276. HXStream* pStream = (HXStream*) (*lIter);
  277. pStream->Release();
  278.     }
  279.     m_HXStreamList.RemoveAll();    
  280.     HX_RELEASE(m_pFileHeader);    
  281.     HX_RELEASE(m_pASMSource);
  282.     HX_RELEASE(m_pBackChannel);
  283. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  284.     HX_RELEASE(m_pUpgradeCollection);
  285. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  286.     m_bForcedSourceEnd = FALSE;
  287.     m_bSourceEnd = FALSE;
  288.     HX_DELETE(m_pRedirectURL);
  289.     m_bRedirectPending  = FALSE;
  290. #if defined(HELIX_FEATURE_RECORDCONTROL)
  291.     if(m_pRecordControl)
  292.     {
  293. m_pRecordControl->Cleanup();
  294.     }
  295. #endif /* HELIX_FEATURE_RECORDCONTROL */
  296.     HX_RELEASE(m_pRecordControl);
  297.     return HXR_OK;
  298. }
  299. /////////////////////////////////////////////////////////////////////////
  300. // Method:
  301. // IUnknown::QueryInterface
  302. // Purpose:
  303. // Implement this to export the interfaces supported by your 
  304. // object.
  305. //
  306. STDMETHODIMP HXSource::QueryInterface(REFIID riid, void** ppvObj)
  307. {
  308.     QInterfaceList qiList[] =
  309.         {
  310.             { GET_IIDHANDLE(IID_IHXStreamSource), (IHXStreamSource*)this },
  311.             { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
  312.             { GET_IIDHANDLE(IID_IHXInfoLogger), (IHXInfoLogger*)this },
  313.             { GET_IIDHANDLE(IID_IHXPrivateStreamSource), (IHXPrivateStreamSource*)this },
  314.             { GET_IIDHANDLE(IID_IHXSourceBufferingStats), (IHXSourceBufferingStats*)this },
  315.             { GET_IIDHANDLE(IID_IHXSourceBufferingStats2), (IHXSourceBufferingStats2*)this },
  316. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  317.             { GET_IIDHANDLE(IID_IHXHyperNavigate), (IHXHyperNavigate*)this },
  318.             { GET_IIDHANDLE(IID_IHXHyperNavigate2), (IHXHyperNavigate2*)this },
  319. #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
  320.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXStreamSource*)this },
  321.         };
  322.     
  323.     HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  324.     
  325.     // if successful, return immediately...
  326.     if (SUCCEEDED(res))
  327.     {
  328.         return res;
  329.     }
  330.     // ... otherwise proceed onward
  331.     
  332.     if (IsEqualIID(riid, IID_IHXBackChannel))
  333.     {
  334. if (m_pBackChannel)
  335. {
  336.     AddRef();
  337.     *ppvObj = (IHXBackChannel*)this;
  338.     return HXR_OK;
  339. }
  340. else
  341. {
  342.     *ppvObj = NULL;
  343.     return HXR_NOINTERFACE;
  344. }
  345.     }
  346.     else if (IsEqualIID(riid, IID_IHXASMSource))
  347.     {
  348. if (m_pASMSource)
  349. {
  350.     AddRef();
  351.     *ppvObj = (IHXASMSource*)this;
  352.     return HXR_OK;
  353. }
  354. else
  355. {
  356.     *ppvObj = NULL;
  357.     return HXR_NOINTERFACE;
  358. }
  359.     }
  360. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  361.     else if (IsEqualIID(riid, IID_IHXUpgradeCollection))
  362.     {
  363. if (!m_pUpgradeCollection)
  364. {
  365.     m_pUpgradeCollection = new HXUpgradeCollection;
  366.     m_pUpgradeCollection->AddRef();
  367. }
  368. return m_pUpgradeCollection->QueryInterface(riid, ppvObj);
  369.     }
  370. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  371.     else if (m_pRequest &&
  372. m_pRequest->QueryInterface(riid, ppvObj) == HXR_OK)
  373.     {
  374. return HXR_OK;
  375.     }
  376.     else if (m_pFileHeader &&
  377. m_pFileHeader->QueryInterface(riid, ppvObj) == HXR_OK)
  378.     {
  379. return HXR_OK;
  380.     }
  381.     *ppvObj = NULL;
  382.     return HXR_NOINTERFACE;
  383. }
  384. /////////////////////////////////////////////////////////////////////////
  385. // Method:
  386. // IUnknown::AddRef
  387. // Purpose:
  388. // Everyone usually implements this the same... feel free to use
  389. // this implementation.
  390. //
  391. STDMETHODIMP_(ULONG32) HXSource::AddRef()
  392. {
  393.     return InterlockedIncrement(&m_lRefCount);
  394. }
  395. /////////////////////////////////////////////////////////////////////////
  396. // Method:
  397. // IUnknown::Release
  398. // Purpose:
  399. // Everyone usually implements this the same... feel free to use
  400. // this implementation.
  401. //
  402. STDMETHODIMP_(ULONG32) HXSource::Release()
  403. {
  404.     if (InterlockedDecrement(&m_lRefCount) > 0)
  405.     {
  406. return m_lRefCount;
  407.     }
  408.     delete this;
  409.     return 0;
  410. }
  411. // *** IHXStreamSource methods ***
  412. /************************************************************************
  413.  * Method:
  414.  * IHXStreamSource::IsLive
  415.  * Purpose:
  416.  * Ask the source whether it is live
  417.  *
  418.  */
  419. STDMETHODIMP_ (BOOL) HXSource::IsLive(void)
  420. {
  421.     return mLiveStream;
  422. }
  423. /************************************************************************
  424.  * Method:
  425.  *     IHXStreamSource::GetPlayer
  426.  * Purpose:
  427.  *     Get the interface to the player object of which the source is
  428.  *     a part of.
  429.  *
  430.  */
  431. STDMETHODIMP HXSource::GetPlayer(IHXPlayer* &pPlayer)
  432. {
  433.     pPlayer = m_pPlayer;
  434.     if (pPlayer)
  435.     {
  436. pPlayer->AddRef();
  437.     }
  438.     return HXR_OK;
  439. }
  440. /************************************************************************
  441.  * Method:
  442.  *     IHXStreamSource::GetContext
  443.  * Purpose:
  444.  *     Get the interface to the context object of which the source is
  445.  *     a part of.
  446.  *
  447.  */
  448. STDMETHODIMP HXSource::GetContext(IUnknown* &pContext)
  449. {
  450.     pContext = ((IUnknown*)(IHXClientEngine*) m_pEngine);
  451.     if (pContext)
  452.     {
  453. pContext->AddRef();
  454.     }
  455.     return HXR_OK;
  456. }
  457. /************************************************************************
  458.  * Method:
  459.  *     IHXStreamSource::GetURL
  460.  * Purpose:
  461.  *     Get the URL for this source. NOTE: The returned string is
  462.  *     assumed to be valid for the life of the IHXStreamSource from which it
  463.  *     was returned.
  464.  *
  465.  */
  466. STDMETHODIMP_(const char*) HXSource::GetURL(void)
  467. {
  468.     const char* pURL = NULL;
  469.     /* 
  470.      * Make sure that the we have not been re-directed
  471.      * to a new URL.
  472.      */ 
  473.     if (m_pRequest && 
  474. m_pRequest->GetURL(pURL) == HXR_OK &&
  475. pURL)
  476.     {
  477. if (!m_pszURL ||
  478.     ::strcasecmp(pURL, m_pszURL) != 0)
  479. {
  480.     HX_VECTOR_DELETE(m_pszURL);
  481.     m_pszURL = new char[strlen(pURL) + 1];
  482.     strcpy(m_pszURL, pURL); /* Flawfinder: ignore */
  483. }
  484.     }
  485.     // append RAM mimeType as URL option to notify the
  486.     // caller(i.e. ViewSource)
  487.     if (m_bIsMeta)
  488.     {
  489. char* pszTemp = NULL;
  490. pszTemp = ::HXFindChar(m_pszURL, '?');
  491. if (pszTemp)
  492. {
  493. int lenTemp = strlen(m_pszURL) + strlen("&mimeType=") + strlen(RAM_MIMETYPE) + 1;
  494.     pszTemp = new char[lenTemp];
  495.     SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "&mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
  496. }
  497. else
  498. {
  499. int lenTemp = strlen(m_pszURL) + strlen("?mimeType=") + strlen(RAM_MIMETYPE) + 1;
  500.     pszTemp = new char[lenTemp];
  501.     SafeSprintf(pszTemp, lenTemp, "%s%s%s", m_pszURL, "?mimeType=", RAM_MIMETYPE); /* Flawfinder: ignore */
  502. }
  503. HX_VECTOR_DELETE(m_pszURL);
  504. m_pszURL = pszTemp;
  505.     }
  506.     return m_pszURL;
  507. }
  508. /************************************************************************
  509.  * Method:
  510.  *     IHXStreamSource::GetStreamCount
  511.  * Purpose:
  512.  *     Get the number of streams in this source
  513.  *
  514.  */
  515. STDMETHODIMP_(UINT16)
  516. HXSource::GetStreamCount()
  517. {
  518.     return m_HXStreamList.GetCount();
  519. }
  520. /************************************************************************
  521.  * Method:
  522.  *     IHXStreamSource::GetStream
  523.  * Purpose:
  524.  *     Get the stream with the given index.
  525.  * Note: 
  526.  *     Since stream numbers may not be zero based, stream index is not
  527.  *     equal to the stream number. Actual stream number may be determined 
  528.  *     from IHXStream::GetStreamNumber()
  529.  *
  530.  */
  531. STDMETHODIMP
  532. HXSource::GetStream
  533. (
  534.     UINT16 nIndex,
  535.     REF(IUnknown*) pUnknown
  536. )
  537. {
  538.     LISTPOSITION lPosition = m_HXStreamList.FindIndex((int) nIndex);
  539.     if (!lPosition)
  540.     {
  541. pUnknown = NULL;
  542. return HXR_INVALID_PARAMETER;
  543.     }
  544.     HXStream* pStream = (HXStream*) m_HXStreamList.GetAt(lPosition);
  545.     HX_ASSERT(pStream);
  546.     return pStream->QueryInterface(IID_IUnknown,(void**)&pUnknown);
  547. }
  548. // IHXPrivateStreamSource methods 
  549. STDMETHODIMP_(BOOL) HXSource::IsSaveAllowed()
  550. {
  551.     return mSaveAsAllowed;
  552. }
  553. /*
  554.  * IHXBackChannel method
  555.  */
  556. /************************************************************************
  557.  * Method:
  558.  *     IHXBackChannel::PacketReady
  559.  * Purpose:
  560.  *      A back channel packet sent from Renderer to FileFormat plugin.
  561.  */
  562. STDMETHODIMP
  563. HXSource::PacketReady(IHXPacket* pPacket)
  564. {
  565.     HX_ASSERT(m_pBackChannel);
  566.     if (m_pBackChannel)
  567.     {
  568. return m_pBackChannel->PacketReady(pPacket);
  569.     }
  570.     return HXR_FAIL;
  571. }
  572. /*
  573.  * IHXASMSource methods
  574.  */
  575. /************************************************************************
  576.  * Method:
  577.  *     IHXASMSource::Subscribe
  578.  * Purpose:
  579.  *      Called to inform a file format that a subscription has occurred,
  580.  *     to rule number uRuleNumber, for stream uStreamNumber.
  581.  */
  582. STDMETHODIMP
  583. HXSource::Subscribe(UINT16 uStreamNumber,
  584.      UINT16 uRuleNumber)
  585. {
  586.     HX_ASSERT(m_pASMSource);
  587.     if (m_pASMSource)
  588.     {
  589. return m_pASMSource->Subscribe(uStreamNumber, uRuleNumber);
  590.     }
  591.     return HXR_FAIL;
  592. }
  593. /************************************************************************
  594.  * Method:
  595.  *     IHXASMSource::Unsubscribe
  596.  * Purpose:
  597.  *      Called to inform a file format that a unsubscription has occurred,
  598.  *     to rule number uRuleNumber, for stream uStreamNumber.
  599.  */
  600. STDMETHODIMP
  601. HXSource::Unsubscribe(UINT16 uStreamNumber,
  602.        UINT16 uRuleNumber)
  603. {
  604.     HX_ASSERT(m_pASMSource);
  605.     if (m_pASMSource)
  606.     {
  607. return m_pASMSource->Unsubscribe(uStreamNumber, uRuleNumber);
  608.     }
  609.     return HXR_FAIL;
  610. }
  611. void
  612. HXSource::AddHXStream(HXStream* pStream)
  613. {
  614.     pStream->AddRef();
  615.     m_HXStreamList.AddTail(pStream);
  616.     UINT16 uStreamNumber = pStream->GetStreamNumber();
  617.     STREAM_INFO* pStreamInfo;
  618.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  619.     {
  620. pStreamInfo->m_pStream = pStream;
  621. pStreamInfo->m_pStream->AddRef();
  622. pStreamInfo->BufferingState().OnStream((IHXStream*)pStream);
  623.     }
  624. }
  625. HX_RESULT
  626. HXSource::CollectAudioStreams(CHXSimpleList*& pAudioStreamList)
  627. {
  628. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  629.     HX_RESULT     rc = HXR_OK;
  630.     UINT16     i = 0;
  631.     UINT16     uNumAudioStreams = 0;
  632.     CHXAudioPlayer* pAudioPlayer = NULL;
  633.     CHXAudioStream* pCHXAudioStream = NULL;
  634.     IHXValues*     pHeader = NULL;
  635.     pAudioStreamList = NULL;
  636.     if (!m_pPlayer)
  637.     {
  638. goto cleanup;
  639.     }
  640.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  641.     if (!pAudioPlayer)
  642.     {
  643. goto cleanup;
  644.     }
  645.     uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
  646.     for (i = 0; i < uNumAudioStreams; i++)
  647.     {
  648. pCHXAudioStream = pAudioPlayer->GetCHXAudioStream(i);
  649. pCHXAudioStream->AddRef();
  650. pHeader = ((IHXAudioStream*)pCHXAudioStream)->GetStreamInfo();
  651. if (pHeader &&
  652.     IsAudioStreamFromThisSource(pHeader))
  653. {
  654.     if (!pAudioStreamList)
  655.     {
  656. pAudioStreamList = new CHXSimpleList();
  657.     }
  658.     pAudioStreamList->AddTail(pCHXAudioStream);
  659. }
  660. else
  661. {
  662.     HX_RELEASE(pCHXAudioStream);
  663. }
  664. HX_RELEASE(pHeader);
  665.     }
  666. cleanup:
  667.     if (!pAudioStreamList)
  668.     {  
  669. rc = HXR_FAILED;
  670.     }
  671.     return rc;
  672. #else
  673.     return HXR_NOTIMPL;
  674. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  675. }
  676. void
  677. HXSource::RemoveAudioStreams(void)
  678. {    
  679. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  680.     CHXAudioPlayer* pAudioPlayer = NULL;
  681.     CHXSimpleList*  pAudioStreamList = NULL;
  682.     if (!m_pPlayer)
  683.     {
  684. goto cleanup;
  685.     }
  686.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  687.     if (!pAudioPlayer)
  688.     {
  689. goto cleanup;
  690.     }
  691.     pAudioPlayer->AddRef();
  692.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  693.     {
  694. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_REMOVE);
  695. ReleaseAudioStreams(pAudioStreamList);
  696. HX_DELETE(pAudioStreamList);
  697.     }
  698.     HX_RELEASE(pAudioPlayer);
  699. cleanup:
  700. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  701.     return;
  702. }
  703. void
  704. HXSource::PauseAudioStreams(void)
  705. {
  706. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  707.     CHXAudioPlayer* pAudioPlayer = NULL;
  708.     CHXSimpleList*  pAudioStreamList = NULL;
  709.     if (!m_pPlayer)
  710.     {
  711. goto cleanup;
  712.     }
  713.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  714.     if (!pAudioPlayer)
  715.     {
  716. goto cleanup;
  717.     }
  718.     pAudioPlayer->AddRef();
  719.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  720.     {
  721. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_PAUSE);
  722. ReleaseAudioStreams(pAudioStreamList);
  723. HX_DELETE(pAudioStreamList);
  724.     }
  725.     HX_RELEASE(pAudioPlayer);
  726. cleanup:
  727. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  728.     return;
  729. }
  730. void
  731. HXSource::ResumeAudioStreams(void)
  732. {
  733. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  734.     CHXAudioPlayer* pAudioPlayer = NULL;
  735.     CHXSimpleList*  pAudioStreamList = NULL;
  736.     if (!m_pPlayer)
  737.     {
  738. goto cleanup;
  739.     }
  740.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  741.     if (!pAudioPlayer)
  742.     {
  743. goto cleanup;
  744.     }
  745.     pAudioPlayer->AddRef();
  746.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  747.     {
  748. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_RESUME);
  749. ReleaseAudioStreams(pAudioStreamList);
  750. HX_DELETE(pAudioStreamList);
  751.     }
  752.     HX_RELEASE(pAudioPlayer);
  753. cleanup:
  754. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  755.     return;
  756. }
  757. void
  758. HXSource::ReleaseAudioStreams(CHXSimpleList* pAudioStreamList)
  759. {
  760. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  761.     if (pAudioStreamList && !pAudioStreamList->IsEmpty())
  762.     {
  763. CHXSimpleList::Iterator lIter = pAudioStreamList->Begin();
  764. for (; lIter != pAudioStreamList->End(); ++lIter)
  765. {
  766.     CHXAudioStream* pAudioStream = (CHXAudioStream*) (*lIter);
  767.     HX_RELEASE(pAudioStream);
  768. }
  769.     }
  770. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  771.     return;
  772. }
  773. HX_RESULT HXSource::Init(HXPlayer * pPlayer, UINT32 unRegistryID)
  774. {
  775.     HX_RESULT theErr = HXR_OK;
  776.    
  777.     m_pPlayer = pPlayer;
  778.     if (m_pPlayer->QueryInterface(IID_IHXPreferences, (void **) &m_pPreferences) != HXR_OK)
  779.     {
  780. theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
  781.     }
  782.     m_pBufferManager = new CBufferManager(this);
  783.     if(!m_pBufferManager)
  784.     {
  785.         theErr = HXR_OUTOFMEMORY;
  786.     }
  787.     // create registry entries
  788.     if (HXR_OK != m_pPlayer->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry))
  789.     {
  790. m_pRegistry = NULL;
  791.     }
  792.     else
  793.     {
  794. m_ulRegistryID = unRegistryID;
  795.     }
  796.     if (!theErr &&
  797. m_pPlayer->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler) != HXR_OK)
  798.     {
  799. theErr = HXR_INVALID_PARAMETER; //HX_INVALID_INTERFACE;
  800.     }
  801.     IHXPreferences* pPref = NULL;
  802.     m_pPlayer->QueryInterface(IID_IHXPreferences, (void**)&pPref);
  803.     if (HXR_OK == ReadPrefINT32(pPref, "TurboPushdown", m_ulTurboPushDown))
  804.     {
  805. m_ulTurboPushDown = (m_ulTurboPushDown / 100) * 100;  // round to multiple of 100
  806.     }
  807.     HX_RELEASE(pPref);
  808.     m_pEngine = m_pPlayer->m_pEngine;
  809.     m_pEngine->AddRef();
  810.     return theErr;
  811. }
  812. HX_RESULT HXSource::SetupRegistry()
  813. {
  814.     HX_RESULT theErr = HXR_OK;
  815. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  816.     UINT32 ulRepeatedRegistryID = 0;
  817.     IHXBuffer* pRepeatRegName = NULL;
  818.     char        szSourceName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  819.     HX_ASSERT(m_pSourceInfo);    
  820.     if (m_pSourceInfo->m_bLeadingSource &&
  821. !m_pSourceInfo->m_pRepeatList)
  822.     {
  823. m_pStats = new SOURCE_STATS(m_pRegistry, m_ulRegistryID);
  824.     }
  825.     else if (m_pRegistry && 
  826.     HXR_OK == m_pRegistry->GetPropName(m_pPlayer->m_ulRepeatedRegistryID, pRepeatRegName))
  827.     {
  828. SafeSprintf(szSourceName, MAX_DISPLAY_NAME, "%s.%ld%ld%ld", 
  829. pRepeatRegName->GetBuffer(),
  830. m_pSourceInfo->m_uGroupID,
  831. m_pSourceInfo->m_uTrackID,
  832. (int)m_pSourceInfo->m_bLeadingSource);
  833.     
  834. ulRepeatedRegistryID = m_pRegistry->GetId(szSourceName);
  835. if (!ulRepeatedRegistryID)
  836. {
  837.     ulRepeatedRegistryID = m_pRegistry->AddComp(szSourceName);
  838. }
  839. m_pStatsManager = new StatsManager(m_pRegistry, m_ulRegistryID, ulRepeatedRegistryID);
  840. m_pStatsManager->AddRef();
  841. m_pStats = new SOURCE_STATS(m_pRegistry, ulRepeatedRegistryID);
  842.         if( !m_pStats )
  843.         {
  844.             theErr = HXR_OUTOFMEMORY;
  845.         }
  846.     }
  847.     else
  848.     {
  849. // why stats' creation failed??
  850. HX_ASSERT(FALSE);
  851.     }
  852.     HX_RELEASE(pRepeatRegName);
  853. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  854.     return theErr;
  855. }
  856. HX_RESULT HXSource::ReadPreferences(void)
  857. {
  858.     UINT32      un16Temp = 10;
  859.     ReadPrefINT32(m_pPreferences, "PerfectPlayTime", un16Temp); 
  860.     m_ulPerfectPlayTime = un16Temp;
  861.     ReadPrefINT32(m_pPreferences, "BufferedPlayTime", un16Temp);
  862.     m_ulBufferedPlayTime = un16Temp;
  863.     ReadPrefBOOL(m_pPreferences, "PerfPlayEntireClip", m_bPerfectPlayEntireClip); 
  864.     return HXR_OK;
  865. }
  866. HX_RESULT HXSource::DeleteStreamTable(void)
  867. {
  868.     HX_RESULT theErr = HXR_OK;
  869.     STREAM_INFO * sInfo = NULL;
  870.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  871.          i != mStreamInfoTable->End(); ++i) 
  872.     {    
  873. sInfo = (STREAM_INFO*) (*i);
  874. if (sInfo)
  875. {
  876.     HX_DELETE (sInfo);
  877. }
  878.     }
  879.     mStreamInfoTable->RemoveAll();
  880.     m_ulStreamIndex = 0;
  881.     m_uNumStreams = 0;
  882.     
  883.     return theErr;
  884. }
  885. IHXValues* HXSource::GetHeaderInfo(UINT16 stream_number)
  886. {
  887.     STREAM_INFO * pStreamInfo;
  888.     if (mStreamInfoTable->Lookup((LONG32) stream_number, (void*& )pStreamInfo))
  889.     {
  890. return pStreamInfo->m_pHeader;
  891.     }
  892.     else
  893.     {
  894. return NULL;
  895.     }
  896. }
  897. HX_RESULT
  898. HXSource::GetStreamHeaderInfo(UINT16 index, IHXValues*& hdr)
  899. {
  900.     HX_TRACE("HXSource::GetStreamHeaderInfo");
  901.     
  902.     // sanity check
  903.     if (index >= m_uNumStreams)
  904.     {
  905. return HXR_INVALID_PARAMETER; // HX_INVALID_INDEX;
  906.     }
  907.     
  908.     CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  909.     for (UINT16 j=0; j < index; j++)
  910.     {
  911. ++i;
  912.     }
  913.     STREAM_INFO* pStreamInfo = (STREAM_INFO*) *i;
  914.     hdr = pStreamInfo->m_pHeader;
  915.     if (hdr)
  916.     {
  917. hdr->AddRef();
  918.     }
  919.     return HXR_OK;
  920. }
  921. void HXSource::SetFlags(UINT16 flags)
  922. {
  923.     mFlags = flags;
  924.     if (mFlags & HX_PERFECT_PLAY_ENABLED)
  925.     {
  926. m_bPerfectPlayAllowed = TRUE;
  927.     }
  928.     else
  929.     {
  930. m_bPerfectPlayAllowed = FALSE;
  931.     }
  932.     if (mFlags & HX_SAVE_ENABLED)
  933.     {
  934. mSaveAsAllowed = TRUE;
  935.     }
  936.     else
  937.     {
  938. mSaveAsAllowed = FALSE;
  939.     }
  940. }
  941. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  942. HX_RESULT HXSource::CopyMetaDataToRegistry(IHXValues* pHeader)
  943. {
  944.     // get Request Object
  945.     char pszServerMetaData[256] = {0}; /* Flawfinder: ignore */
  946.     char pszMetaData[256] = {0}; /* Flawfinder: ignore */
  947.     IHXValues* pReqHeaders = NULL;
  948.     IHXRequest* pRequest = NULL;
  949.     IHXBuffer* pBuffer = NULL;
  950.     char szRegKeyName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  951.     char buff[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  952.     char szSMDKey[256]; /* Flawfinder: ignore */
  953.     ULONG32 ulValue = 0;
  954.     IHXBuffer* pParentName = NULL;
  955.     UINT32 regid = 0;
  956.     const char szServerMetaData[] = {"ServerMetaData"};
  957.     if (HXR_OK == m_pRegistry->GetPropName(m_pStats->m_ulRegistryID, pParentName))
  958.     {
  959. SafeStrCpy(buff, (const char*) pParentName->GetBuffer(), MAX_DISPLAY_NAME);
  960. char* pDot = strrchr(buff, '.');
  961. if (pDot)
  962. {
  963.     *pDot = '';
  964. }
  965. SafeStrCpy(szSMDKey, buff, 256);
  966. if (HXR_OK == GetRequest(pRequest))
  967. {
  968.     // get request headers
  969.     if (HXR_OK == pRequest->GetRequestHeaders(pReqHeaders))
  970.     {
  971. // look for the meta data properties
  972. if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptMetaInfo", pBuffer))
  973. {
  974.     SafeStrCpy(pszMetaData, (char*) pBuffer->GetBuffer(), 256);
  975.     HX_RELEASE(pBuffer);
  976.     // look for comma delimited entries
  977.     const char* pCharEntryStart = pszMetaData;
  978.     const char* pCharEntryEnd = pCharEntryStart;
  979.     while (pCharEntryEnd && *pCharEntryEnd)
  980.     {
  981. ++pCharEntryEnd;
  982. if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
  983. {
  984.     // copy next prop request into buffer 
  985.     strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
  986.     *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = '';
  987.     // see if this prop is in file header (it should be!)
  988.     if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
  989.     {
  990. // create new registry entry
  991. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
  992. regid = m_pRegistry->GetId(szRegKeyName);
  993. if (!regid)
  994. {
  995.     m_pRegistry->AddStr(szRegKeyName, pBuffer);
  996. }
  997. else
  998. {
  999.     // set new value
  1000.     m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
  1001. }
  1002. HX_RELEASE(pBuffer);
  1003.     }
  1004.     else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
  1005.     {
  1006. // create new registry entry
  1007. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", pParentName->GetBuffer(), buff);
  1008. regid = m_pRegistry->GetId(szRegKeyName);
  1009. if (!regid)
  1010. {
  1011.     m_pRegistry->AddInt(szRegKeyName, ulValue);
  1012. }
  1013. else
  1014. {
  1015.     // set new value
  1016.     m_pRegistry->SetIntByName(szRegKeyName, ulValue);
  1017. }
  1018.     }
  1019.     pCharEntryStart = pCharEntryEnd + 1;
  1020. }
  1021.     }
  1022. }
  1023. // look for the meta data properties
  1024. if (HXR_OK == pReqHeaders->GetPropertyCString("AcceptServerMetaData", pBuffer))
  1025. {
  1026.     SafeStrCpy(pszServerMetaData, (char*) pBuffer->GetBuffer(), 256);
  1027.     HX_RELEASE(pBuffer);
  1028.     // first make sure we have a composit key for "statistics.Player0.ServerMetaData"
  1029.     SafeSprintf(buff, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, szServerMetaData);
  1030.     regid = m_pRegistry->GetId(buff);
  1031.     if (!regid)
  1032.     {
  1033. m_pRegistry->AddComp(buff);
  1034.     }
  1035.     SafeStrCpy(szSMDKey, buff, 256);
  1036.     // look for comma delimited entries
  1037.     const char* pCharEntryStart = pszServerMetaData;
  1038.     const char* pCharEntryEnd = pCharEntryStart;
  1039.     while (pCharEntryEnd && *pCharEntryEnd)
  1040.     {
  1041. ++pCharEntryEnd;
  1042. if (*pCharEntryEnd == ',' || !*pCharEntryEnd)
  1043. {
  1044.     // copy next prop request into buffer 
  1045.     strncpy(buff, pCharEntryStart, (UINT32)pCharEntryEnd - (UINT32)pCharEntryStart); /* Flawfinder: ignore */
  1046.     *(buff+(UINT32)pCharEntryEnd - (UINT32)pCharEntryStart) = '';
  1047.     // see if this prop is in file header (it should be!)
  1048.     if (HXR_OK == pHeader->GetPropertyCString(buff, pBuffer))
  1049.     {
  1050. // create new registry entry (if one does not exist)
  1051. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
  1052. regid = m_pRegistry->GetId(szRegKeyName);
  1053. if (!regid)
  1054. {
  1055.     m_pRegistry->AddStr(szRegKeyName, pBuffer);
  1056. }
  1057. else
  1058. {
  1059.     // set new value
  1060.     m_pRegistry->SetStrByName(szRegKeyName, pBuffer);
  1061. }
  1062. HX_RELEASE(pBuffer);
  1063.     }
  1064.     else if (HXR_OK == pHeader->GetPropertyULONG32(buff, ulValue))
  1065.     {
  1066. // create new registry entry
  1067. SafeSprintf(szRegKeyName, MAX_DISPLAY_NAME, "%s.%s", szSMDKey, buff);
  1068. regid = m_pRegistry->GetId(szRegKeyName);
  1069. if (!regid)
  1070. {
  1071.     m_pRegistry->AddInt(szRegKeyName, ulValue);
  1072. }
  1073. else
  1074. {
  1075.     // set new value
  1076.     m_pRegistry->SetIntByName(szRegKeyName, ulValue);
  1077. }
  1078.     }
  1079.     pCharEntryStart = pCharEntryEnd + 1;
  1080. }
  1081.     }
  1082. }
  1083. HX_RELEASE(pReqHeaders);
  1084.     }
  1085.     HX_RELEASE(pRequest);
  1086. }
  1087. HX_RELEASE(pParentName);
  1088.     }
  1089.     return HXR_OK;
  1090. }
  1091. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1092. HX_RESULT HXSource::SetPlayTimes(UINT32 ulStartTime, 
  1093.   UINT32 ulEndTime, 
  1094.   UINT32 ulDelay, 
  1095.   UINT32 ulDuration)
  1096. {
  1097.     m_ulStartTime     = ulStartTime;
  1098.     m_ulEndTime     = ulEndTime;
  1099.     /* We do not handle Delay field for now */
  1100.     m_ulDelay     = ulDelay;
  1101.     m_ulRestrictedDuration  = ulDuration;
  1102.     if (m_ulEndTime > 0)
  1103.     {
  1104. m_bCustomEndTime = TRUE;
  1105.     }
  1106.     else
  1107.     {
  1108.      m_bCustomEndTime = FALSE;
  1109.     }
  1110.     return HXR_OK;
  1111. }
  1112. HX_RESULT
  1113. HXSource::UpdatePlayTimes(IHXValues* pValues)
  1114. {
  1115.     HX_RESULT rc = HXR_OK;
  1116.     char szStart[] = "Start";
  1117.     char szEnd[] = "End";
  1118.     char szDelay[] = "Delay";
  1119.     char szDuration[] = "Duration";
  1120.     UINT32 ulStartTime = 0;
  1121.     UINT32 ulEndTime = 0;
  1122.     UINT32 ulDelay = 0;
  1123.     UINT32 ulRestrictedDuration = 0;
  1124.     pValues->GetPropertyULONG32(szStart, ulStartTime);
  1125.     pValues->GetPropertyULONG32(szEnd, ulEndTime);
  1126.     pValues->GetPropertyULONG32(szDelay, ulDelay);
  1127.     pValues->GetPropertyULONG32(szDuration, ulRestrictedDuration);
  1128.     if (ulStartTime != m_ulStartTime    ||
  1129. ulEndTime != m_ulEndTime     ||
  1130. ulDelay != m_ulDelay     ||
  1131. ulRestrictedDuration != m_ulRestrictedDuration)
  1132.     {
  1133. SetPlayTimes(ulStartTime, ulEndTime, ulDelay, ulRestrictedDuration);
  1134. rc = AdjustClipTime();
  1135.     }
  1136.     return rc;
  1137. }
  1138. ULONG32 
  1139. HXSource::GetPerfectPlayTime(void)
  1140. {
  1141.     ULONG32 ulCurrentPlayTime = m_pPlayer ? m_pPlayer->GetCurrentPlayTime() : 0;
  1142.     ULONG32 result       = m_bPerfectPlay ? m_ulPerfectPlayTime : m_ulBufferedPlayTime;
  1143.     if (m_ulDuration != 0)
  1144.     {
  1145. // mPlaybackLength is in Milliseconds, we want to calculate
  1146. // playback in seconds...
  1147. ULONG32 playbackTimeLeftInClip = 
  1148.     ((m_ulDuration > ulCurrentPlayTime ? m_ulDuration - ulCurrentPlayTime : 0) /1000)+1;
  1149. /* Perfect Play entire clip ONLY if user has chosen PerfectPlay specifically
  1150.  * If we internally go in buffered play mode, always use perfect play time
  1151.  * setting.
  1152.  */
  1153. if (m_bPerfectPlay)
  1154. {
  1155.     if (m_bPerfectPlayEntireClip)
  1156.     {
  1157. result = playbackTimeLeftInClip;
  1158.     }
  1159.     else
  1160.     {
  1161. result = min(m_ulPerfectPlayTime, playbackTimeLeftInClip);
  1162.     }
  1163. }
  1164. else // if (m_bBufferedPlay)
  1165. {
  1166.     result = min(m_ulBufferedPlayTime, playbackTimeLeftInClip);
  1167. }
  1168.     }
  1169.     
  1170.     // check if enough memory is available to handle the result
  1171.     if(result > 0)
  1172.     {
  1173. // get 50% of the available memory
  1174. ULONG32 maxMemAvail = GetAvailableMemory() / 2;
  1175. ULONG32 bytesPerSecond = m_ulAvgBandwidth/8;
  1176. ULONG32 maxTimeAvail = maxMemAvail/(bytesPerSecond > 0 ? bytesPerSecond : 1);
  1177. // if this is true then we can't buffer the entire clip
  1178. if (maxTimeAvail < result)
  1179. m_bCannotBufferEntireClip = (m_bPerfectPlayEntireClip) ? TRUE : FALSE;
  1180. else
  1181. m_bCannotBufferEntireClip = FALSE;
  1182. result = min(result,maxTimeAvail);
  1183.     }
  1184.     /* Value now returned in ms. */
  1185.     return 1000*(max(result, PERFECTPLAY_MIN_TIME));
  1186. }
  1187. STDMETHODIMP 
  1188. HXSource::ReportRebufferStatus(UINT16 uStreamNumber,
  1189.         UINT8 unNeeded, 
  1190.         UINT8 unAvailable) 
  1191. {
  1192.     STREAM_INFO* pStreamInfo = 0;
  1193. //    if (m_bDelayed ||
  1194. // (m_ulDelay > 0 && m_ulDelay > m_pPlayer->GetCurrentPlayTime()))
  1195.     if (m_bDelayed)
  1196.     {
  1197. return HXR_OK;
  1198.     }
  1199.     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ReportRebufferStatus %lu %lu %lu", this, uStreamNumber, unNeeded, unAvailable));
  1200.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1201.     {
  1202. pStreamInfo->m_unNeeded     = unNeeded;
  1203. pStreamInfo->m_unAvailable  = unAvailable;
  1204. if (unNeeded > unAvailable)
  1205. {
  1206. //     dfprintf("buff", "reportrebufferstatus: %lun", m_pPlayer->GetInternalCurrentPlayTime());     
  1207. //     g_bRahulLog = TRUE;
  1208.     if (m_bFastStart)
  1209.     {
  1210.                 DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)ALMOST Turbo OFF ReportRebufferStatus", this));
  1211.                 //with surestream audio only clips, rarender may report buffering immediately after resume
  1212.                 if (m_bSureStreamClip)
  1213. {
  1214.     if (CALCULATE_ELAPSED_TICKS(m_ulTurboStartActiveTime, HX_GET_TICKCOUNT()) > 1000)
  1215.     {
  1216. LeaveFastStart(TP_OFF_BY_REBUFFER);
  1217. DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
  1218.     }
  1219. }
  1220. else
  1221. {
  1222.                     LeaveFastStart(TP_OFF_BY_REBUFFER);
  1223.                     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Turbo OFF ReportRebufferStatus", this));
  1224. }
  1225.     }
  1226.     // log rebuffer action
  1227.     LogInformation("BUFBEG", NULL);
  1228.     
  1229.     DoRebuffer();
  1230.   }
  1231. else
  1232. {
  1233.     m_bRebufferingRequired = IsRebufferRequired();
  1234.     if (!m_bRebufferingRequired)
  1235.     {
  1236. // log rebuffer action
  1237. LogInformation("BUFEND", NULL);
  1238.     }
  1239. }
  1240.         return HXR_OK;
  1241.     }
  1242.     return HXR_UNEXPECTED;
  1243. }
  1244. STDMETHODIMP 
  1245. HXSource::SetGranularity
  1246. (
  1247.     UINT16 uStreamNumber,
  1248.     ULONG32 ulGranularity
  1249. {
  1250.     STREAM_INFO* pStreamInfo = 0;
  1251.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1252.     {
  1253. m_pPlayer->SetGranularity(this, uStreamNumber, ulGranularity);
  1254. return HXR_OK;
  1255.     }
  1256.     else
  1257.     {
  1258. return HXR_OK;
  1259.     }
  1260.     return HXR_UNEXPECTED;
  1261. }
  1262. BOOL
  1263. HXSource::TryResume(void)
  1264. {
  1265.     BOOL    bResume = FALSE;
  1266.     // resume the persistent source ASAP
  1267.     if (m_pSourceInfo && m_pSourceInfo->m_bIsPersistentSource)
  1268.     {
  1269.         m_bDelayed = FALSE;
  1270.         bResume = TRUE;
  1271.     }
  1272.     else if (m_bPaused && m_bDelayed && m_pPlayer &&
  1273.              m_pPlayer->CanBeStarted(this, m_pSourceInfo, m_bPartOfNextGroup))
  1274.     {
  1275.         UINT32 ulCurrentTime = m_pPlayer->GetInternalCurrentPlayTime();
  1276.         UINT32 ulStartTime = 0;
  1277.         if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
  1278.         {
  1279.             ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
  1280.         }
  1281.         if (ulCurrentTime >= ulStartTime)
  1282.         {
  1283.             m_bDelayed = FALSE;
  1284.             bResume = TRUE;
  1285.         }
  1286.         if (!m_bIsPreBufferingStarted)
  1287.         {
  1288.             m_bIsPreBufferingStarted = TRUE;
  1289.             bResume = TRUE;
  1290.         }
  1291.     }
  1292.     else if (m_bPrefetch)
  1293.     {
  1294.         bResume = TRUE;
  1295.     }
  1296.     if (bResume && CanBeResumed())
  1297.     {
  1298.         if (m_pSourceInfo)
  1299.         {
  1300.             m_pSourceInfo->Register();
  1301.         }
  1302.         m_bResumePending = TRUE;
  1303.     }
  1304.     return bResume;
  1305. }
  1306. BOOL
  1307. HXSource::IsAnyAudioStream(void)
  1308. {
  1309.     IHXAudioPlayer* pAudioPlayer = NULL;
  1310.     BOOL bAtLeastOneAudioStream = FALSE;
  1311.     if (!m_pPlayer)
  1312.     {
  1313. return FALSE;
  1314.     }
  1315.     m_pPlayer->QueryInterface(IID_IHXAudioPlayer, (void **) &pAudioPlayer);
  1316.     UINT16 uNumAudioStreams = pAudioPlayer->GetAudioStreamCount();
  1317.     for (UINT16 i = 0; i < uNumAudioStreams && !bAtLeastOneAudioStream; i++)
  1318.     {
  1319. IHXAudioStream* pAudioStream = pAudioPlayer->GetAudioStream(i);
  1320. IHXValues* pHeader = pAudioStream->GetStreamInfo();
  1321. pAudioStream->Release();
  1322. if (!pHeader)
  1323. {
  1324.     continue;
  1325. }
  1326. if (IsAudioStreamFromThisSource(pHeader))
  1327. {
  1328.     bAtLeastOneAudioStream = TRUE;
  1329.     pHeader->Release();
  1330.     break;
  1331. }
  1332. pHeader->Release();
  1333.     }
  1334.     if (!bAtLeastOneAudioStream)
  1335.     {
  1336.         IHXValues* pHeader = NULL;
  1337.         int nStreamCnt = GetNumStreams();
  1338.         ULONG32     ulIsAudioStream = FALSE;
  1339.         for (int i=0; i<nStreamCnt && !bAtLeastOneAudioStream; i++)
  1340.         {
  1341.             GetStreamHeaderInfo(i, pHeader);
  1342.             pHeader->GetPropertyULONG32("IsAudioStream", ulIsAudioStream);
  1343.             if (ulIsAudioStream)
  1344.             {
  1345.                 bAtLeastOneAudioStream = TRUE;
  1346.             }
  1347.     HX_RELEASE(pHeader);
  1348.         }
  1349.     }
  1350.     pAudioPlayer->Release();
  1351.     return bAtLeastOneAudioStream;
  1352. }
  1353. void
  1354. HXSource::EventReady(CHXEvent* pEvent)
  1355. {
  1356.     if (m_pPlayer)
  1357.     {
  1358. m_pPlayer->EventReady(this, pEvent);
  1359.     }
  1360. }
  1361. BOOL 
  1362. HXSource::IsAudioStreamFromThisSource(IHXValues* pAudioHeader)
  1363. {
  1364.     BOOL bFound = FALSE;
  1365.     CHXMapLongToObj::Iterator ndxStreamIterator = mStreamInfoTable->Begin();
  1366.     for (; ndxStreamIterator != mStreamInfoTable->End(); ++ndxStreamIterator) 
  1367.     {
  1368. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*ndxStreamIterator);
  1369. if (pStreamInfo->m_pHeader == pAudioHeader)
  1370. {
  1371.     bFound = TRUE;
  1372.     break;
  1373. }
  1374.     }
  1375.     return bFound;
  1376. }
  1377. ULONG32
  1378. HXSource::GetAvailableMemory()
  1379. {
  1380.     ULONG32 memAvail = 1000000;
  1381. #if   defined (__MWERKS__)
  1382. //  XXX Hack! We can't call any of the Memory Manager calls at interrupt time so we will have 
  1383. //  to change this to ask our interrupt safe memory allocator how much memory is free
  1384.     memAvail = 1000000;
  1385. #elif defined(_WINCE) && !defined(_WIN32_WCE_EMULATION)
  1386.     STORE_INFORMATION stInfo;
  1387.     GetStoreInformation(&stInfo);
  1388.     memAvail = stInfo.dwFreeSize;
  1389. #elif (_WIN32)
  1390.     MEMORYSTATUS status;
  1391.     status.dwLength = sizeof(MEMORYSTATUS);
  1392.     GlobalMemoryStatus(&status);
  1393.     memAvail = status.dwAvailPageFile;
  1394. #elif defined( _WINDOWS)
  1395.     memAvail = GetFreeSpace(0);
  1396. #elif defined (_UNIX)
  1397.     // XXXX Need to get this to compile.
  1398.     memAvail = 1000000;
  1399. #endif
  1400.     return memAvail;
  1401. }
  1402. void
  1403. HXSource::ReportError(HX_RESULT theErr)
  1404. {
  1405.     if (m_pPlayer)
  1406.     {
  1407. m_pPlayer->ReportError(this, theErr);
  1408.     }
  1409. }
  1410. HX_RESULT
  1411. HXSource::AdjustClipTime(void)
  1412. {
  1413.     HX_RESULT theErr = HXR_OK;
  1414.     UINT32  ulOriginalDuration = m_ulDuration;        
  1415.     UINT32  ulTrackEndTime = 0;
  1416.     CHXMapLongToObj::Iterator i;
  1417.     BOOL    bCustomEndTimeSet = FALSE;
  1418.     if (m_bPartOfPrefetchGroup)
  1419.     {
  1420. if (m_ulDelay)
  1421. {
  1422.     m_ulPrefetchDelay = m_ulDelay;
  1423.     m_bDelayed = TRUE;
  1424.     AdjustClipBandwidthStats(FALSE);
  1425.     DoPause();
  1426. }
  1427. m_ulEndTime = 0;
  1428. m_bCustomEndTime = FALSE;
  1429. goto cleanup;
  1430.     }
  1431.     /* For a live stream, the only qualifiers that make sense
  1432.      * are Duration and Delay. All other qualifiers should be made 0
  1433.      */
  1434.     if (mLiveStream)
  1435.     {
  1436. m_ulStartTime = 0;
  1437. if (!m_bRestrictedLiveStream)
  1438. {
  1439.     m_ulEndTime = 0;
  1440. }
  1441.     }
  1442.     for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i) 
  1443.     {    
  1444. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  1445. ulTrackEndTime = 0;
  1446. HX_RESULT hrTemp = pStreamInfo->m_pHeader->GetPropertyULONG32("EndTime", ulTrackEndTime);
  1447. if (HXR_OK == hrTemp && !m_bCustomEndTime)
  1448. {
  1449.     if (m_ulEndTime < ulTrackEndTime)
  1450.     {
  1451. m_ulEndTime = ulTrackEndTime;
  1452.     }
  1453.     pStreamInfo->m_bCustomEndTime = TRUE;
  1454. }
  1455. else if (m_bCustomEndTime)
  1456. {
  1457.     ulTrackEndTime = m_ulEndTime;
  1458.     pStreamInfo->m_bCustomEndTime = TRUE;
  1459. }
  1460. if (ulTrackEndTime > 0 && !mLiveStream)
  1461. {
  1462.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
  1463. ulTrackEndTime);
  1464.     bCustomEndTimeSet = TRUE;
  1465. }
  1466.     }
  1467.     
  1468.     // if max. duration is set on this source
  1469.     if (m_pSourceInfo && 
  1470. m_pSourceInfo->m_ulMaxDuration)
  1471.     {
  1472. if (m_ulRestrictedDuration)
  1473. {     
  1474.     if (m_ulRestrictedDuration > m_pSourceInfo->m_ulMaxDuration)
  1475.     {
  1476. m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
  1477.     }
  1478. }
  1479. else if (m_ulDuration)
  1480. {
  1481.     if (m_ulDuration > m_pSourceInfo->m_ulMaxDuration)
  1482.     {
  1483. m_ulRestrictedDuration = m_pSourceInfo->m_ulMaxDuration;
  1484.     }
  1485. }
  1486.     }
  1487.     // By default, we always set the end time to be the duration of the clip,
  1488.     // but do not set end time if it was manually specified.
  1489.     if (!bCustomEndTimeSet && !mLiveStream)
  1490.     {
  1491. m_ulEndTime = m_ulDuration;
  1492.     }
  1493.     /* Check if there is any end time */
  1494.     if ((m_ulEndTime < m_ulDuration) || m_bRestrictedLiveStream)
  1495.     {
  1496. m_ulDuration = m_ulEndTime;
  1497.     }
  1498.     
  1499.     /* Is "Delay" specified too? */
  1500.     if (m_ulDelay > 0) 
  1501.     {
  1502. /* Increase duration of this clip */
  1503. m_ulDuration += m_ulDelay;
  1504. UINT32 ulStartTime = 0;
  1505. if (m_ulDelay > m_ulPreRollInMs + NETWORK_FUDGE_FACTOR)
  1506. {
  1507.     ulStartTime = m_ulDelay - (m_ulPreRollInMs + NETWORK_FUDGE_FACTOR);
  1508. }
  1509. // no need to pause delayed persistent component since Pause() will be called
  1510. // on actual tracks' AdjustClipTime() if necessary
  1511. if (m_pSourceInfo && !m_pSourceInfo->m_bIsPersistentSource)
  1512. {
  1513.     m_bDelayed = TRUE;
  1514.     AdjustClipBandwidthStats(FALSE);
  1515.     DoPause();
  1516. }
  1517.     }
  1518.     if (m_ulStartTime > 0) /* reduce duration by start time amount */
  1519.     {
  1520.      if (m_ulDuration > m_ulStartTime)
  1521.      {
  1522.     m_ulDuration -= m_ulStartTime;
  1523. }
  1524. else
  1525. {
  1526.     /* This is bad case. We consider it invalid */
  1527.     m_ulDuration = 0;
  1528. }
  1529.     }
  1530.     /* We now allow to increase the default duration of the clip */
  1531.     if (m_ulRestrictedDuration > 0)
  1532.     {
  1533. m_ulDuration = m_ulRestrictedDuration + m_ulDelay;
  1534. if (mLiveStream && !m_bRestrictedLiveStream)
  1535. {
  1536.     m_bRestrictedLiveStream = TRUE;
  1537.     m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
  1538. }
  1539. if (m_ulEndTime > m_ulRestrictedDuration + m_ulStartTime)
  1540. {
  1541.     m_ulEndTime = m_ulRestrictedDuration + m_ulStartTime;
  1542. }
  1543.     }
  1544.     // orig duration is active duration for this source -- time for which
  1545.     // this source lasts.
  1546.     if (m_ulDuration > m_ulDelay)
  1547.     {
  1548. m_ulOriginalDuration = m_ulDuration - m_ulDelay;
  1549.     }
  1550.     else
  1551.     {
  1552. m_ulOriginalDuration = 0;
  1553.     }
  1554.     if (m_pURL     &&
  1555. rtspProtocol == m_pURL->GetProtocol()     &&
  1556. m_llLastExpectedPacketTime != m_ulEndTime   &&
  1557. !m_bFirstResume)
  1558.     {
  1559. m_bRTSPRuleFlagWorkAround = TRUE;
  1560.     }
  1561.     /* If we receive a packet after this stream, we consider the stream to be done */
  1562.     m_llLastExpectedPacketTime  = CAST_TO_INT64 m_ulEndTime;
  1563.     // Seek to the starting position only if the source
  1564.     // has not been resumed yet
  1565.     if (m_ulStartTime > 0 && m_bFirstResume) 
  1566.     {
  1567. /* We will add m_ulStartTime in DoSeek() call*/
  1568.      theErr = DoSeek(0);
  1569.     }
  1570.     /* Update stream durations if required */
  1571.     for (i = mStreamInfoTable->Begin(); i != mStreamInfoTable->End(); ++i) 
  1572.     {    
  1573. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  1574. if (m_ulStartTime > 0)
  1575. {
  1576.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackStartTime",
  1577.     m_ulStartTime);
  1578. }
  1579. if (m_ulEndTime > 0 && 
  1580.     !mLiveStream    &&
  1581.     HXR_OK != pStreamInfo->m_pHeader->GetPropertyULONG32("TrackEndTime",
  1582.   ulTrackEndTime))
  1583. {
  1584.     pStreamInfo->m_pHeader->SetPropertyULONG32("TrackEndTime",
  1585. m_ulEndTime);
  1586. }
  1587. if (ulOriginalDuration != m_ulDuration)
  1588. {
  1589.     pStreamInfo->m_ulDuration = m_ulDuration;
  1590.     pStreamInfo->m_pHeader->SetPropertyULONG32("Duration", 
  1591. pStreamInfo->m_ulDuration);
  1592. }
  1593. if (m_ulDelay > 0)
  1594. {
  1595.     pStreamInfo->m_pHeader->SetPropertyULONG32("Delay", m_ulDelay);
  1596. }
  1597.     }
  1598. //{FILE* f1 = ::fopen("d:\temp\url.txt", "a+"); ::fprintf(f1, "%p %s %lu %lun", this, m_pszURL, m_ulDelay, m_ulDuration);::fclose(f1);}
  1599. cleanup:
  1600.     m_bClipTimeAdjusted = TRUE;
  1601.     return theErr;
  1602. }
  1603. void
  1604. HXSource::GenerateFakeLostPacket(CHXEvent*& theEvent)
  1605. {
  1606.     IHXPacket* pPacket = theEvent->GetPacket();
  1607.     CHXPacket* pLostPacket = new CHXPacket;
  1608.     pLostPacket->AddRef();
  1609.     pLostPacket->Set(0, 0, pPacket->GetStreamNumber(), 0, 0);
  1610.     pLostPacket->SetAsLost();
  1611.     /* Create a new event with lost packet */
  1612.     CHXEvent* pEvent = new CHXEvent(pLostPacket);
  1613.     pEvent->SetTimeStartPos(theEvent->GetTimeStartPos());
  1614.     pEvent->SetTimeOffset(theEvent->GetTimeOffset());
  1615.     pEvent->SetPreSeekEvent(theEvent->IsPreSeekEvent());
  1616.     pLostPacket->Release();
  1617.     delete theEvent;
  1618.     theEvent = pEvent;
  1619. }
  1620. char*
  1621. HXSource::GetAltURL(BOOL& bDefault)
  1622. {
  1623. #if defined(HELIX_FEATURE_ALT_URL)
  1624.     char*   pAltURL = NULL;
  1625.     if (!m_pURL || m_bInitialized)
  1626.     {
  1627. goto cleanup;
  1628.     }
  1629.     pAltURL = m_pURL->GetAltURL(bDefault);
  1630. cleanup:
  1631.     return pAltURL;
  1632. #else
  1633.     return NULL;
  1634. #endif /* HELIX_FEATURE_ALT_URL */
  1635. }
  1636. HX_RESULT
  1637. HXSource::SetRequest(const CHXURL* pURL, BOOL bAltURL)
  1638. {
  1639.     HX_RESULT hr = HXR_OK;
  1640.     IHXValues* pValues = NULL;
  1641.     IHXValues* pValuesInRequest = NULL;
  1642.     IHXGroup* pGroup = NULL;
  1643.     IHXGroup2* pGroup2 = NULL;
  1644.     IHXGroupManager* pGroupManager = NULL;
  1645.     HX_RELEASE(m_pRequest);
  1646.     if (m_pPlayer)
  1647.     {
  1648. m_pPlayer->GetActiveRequest(m_pRequest);
  1649. if (m_pRequest)
  1650. {
  1651.     m_pPlayer->ResetActiveRequest();
  1652. }
  1653.     }
  1654. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  1655.     if (m_pPlayer && m_pSourceInfo)
  1656.     {
  1657. if (HXR_OK == m_pPlayer->QueryInterface(IID_IHXGroupManager, (void**)&pGroupManager))
  1658. {
  1659.     if (HXR_OK == pGroupManager->GetGroup(m_pSourceInfo->m_uGroupID, pGroup))
  1660.     {
  1661. if (HXR_OK == pGroup->QueryInterface(IID_IHXGroup2, (void**)&pGroup2))
  1662. {
  1663.     pGroup2->GetTrack2(m_pSourceInfo->m_uTrackID, pValues, pValuesInRequest);
  1664.     UINT32 ulValue = 0;
  1665.     char   szDuration[128] = {0}; /* Flawfinder: ignore */
  1666.     IHXBuffer* pBuffer = NULL;
  1667.     if (pValues && HXR_OK == pValues->GetPropertyULONG32("Duration", ulValue))
  1668.     {
  1669. if (!pValuesInRequest)
  1670. {
  1671.     pValuesInRequest = new CHXHeader();
  1672.     if( pValuesInRequest )
  1673.     {
  1674.         pValuesInRequest->AddRef();
  1675.     }
  1676.     else
  1677.     {
  1678.         hr = HXR_OUTOFMEMORY;
  1679.     }
  1680. }
  1681. if (pValuesInRequest)
  1682. {
  1683.     SafeSprintf (szDuration, 128, "%lu", ulValue); /* Flawfinder: ignore */
  1684.     pBuffer = new CHXBuffer();
  1685.     pBuffer->AddRef();
  1686.          pBuffer->Set((UCHAR*)szDuration, strlen(szDuration) + 1);
  1687.     pValuesInRequest->SetPropertyCString("Duration", pBuffer);
  1688.     HX_RELEASE(pBuffer);
  1689. }
  1690.     }
  1691. }
  1692. HX_RELEASE(pGroup2);
  1693.     }
  1694.     HX_RELEASE(pGroup);
  1695. }
  1696. HX_RELEASE(pGroupManager);
  1697.     }
  1698. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  1699.     IHXRegistry* pRegistry = NULL;   
  1700.     m_pEngine->QueryInterface(IID_IHXRegistry, (void**)&pRegistry);
  1701.     hr = ::SetRequest(pURL->GetEscapedURL(), bAltURL, m_pPreferences, pRegistry, pValuesInRequest, m_pRequest);
  1702.     HX_RELEASE(pValues);
  1703.     HX_RELEASE(pValuesInRequest);
  1704.     HX_RELEASE(pRegistry);
  1705. #if defined(HELIX_FEATURE_RECORDCONTROL)
  1706.     if(hr == HXR_OK && pURL->GetProtocol() != fileProtocol)
  1707.     {
  1708. if(!m_pRecordControl)
  1709. {
  1710.     m_pRecordControl = new HXRecordControl((IHXPlayer*)m_pPlayer, (IHXStreamSource*)this);
  1711.     if(m_pRecordControl)
  1712.     {
  1713. m_pRecordControl->AddRef();
  1714. if(m_pRecordControl->IsValid())
  1715.                     m_bPlayFromRecordControl = m_pRecordControl->CanGetPackets();
  1716.                 else
  1717.     HX_RELEASE(m_pRecordControl);
  1718.     }
  1719. }
  1720. if(m_pRecordControl)
  1721. {
  1722.     m_pRecordControl->SetSource((IHXStreamSource*)this);
  1723. }
  1724.     }
  1725. #endif /* HELIX_FEATURE_RECORDCONTROL */
  1726.     return hr;
  1727. }
  1728. void
  1729. HXSource::UpdateDuration(UINT32 ulDuration)
  1730. {
  1731.     CHXSimpleList* pRepeatList = m_pSourceInfo->GetRepeatList();
  1732.     // ulDuration excludes the delay time
  1733.     if (pRepeatList && 
  1734. ulDuration >= (m_ulDuration - m_ulDelay))
  1735.     {
  1736. m_pSourceInfo->m_ulTotalTrackDuration = ulDuration + m_ulDelay;
  1737. if (m_pSourceInfo->m_pPeerSourceInfo)
  1738. {
  1739.     m_pSourceInfo->m_pPeerSourceInfo->m_ulTotalTrackDuration = m_pSourceInfo->m_ulTotalTrackDuration;
  1740. }
  1741.     }
  1742.     else
  1743.     {
  1744. m_ulOriginalDuration = m_ulRestrictedDuration = ulDuration;
  1745. AdjustClipTime();
  1746. m_pSourceInfo->UpdateDuration(m_ulDuration);
  1747.     }
  1748. }
  1749. void
  1750. HXSource::UpdateDelay(UINT32 ulDelay)
  1751. {
  1752.     m_ulDelay = ulDelay;
  1753.     AdjustClipTime();
  1754.     m_pSourceInfo->UpdateDelay(m_ulDelay);
  1755. }
  1756. void
  1757. HXSource::InitialBufferingDone(void)
  1758. {
  1759.     m_bInitialBuffering = FALSE;
  1760.     // resume if we satisfy the initial preroll AND we have issued
  1761.     // rebuffer
  1762.     // note: IsRebufferRequired() should return FALSE!!
  1763.     if (m_bRebufferingRequired)
  1764.     {
  1765. m_bRebufferingRequired = IsRebufferRequired();
  1766. HX_ASSERT(!m_bRebufferingRequired);
  1767.     }
  1768.     return;
  1769. }
  1770. void
  1771. HXSource::DoRebuffer(void)
  1772. {
  1773.     m_bRebufferingRequired  = TRUE;
  1774.     if (m_pPlayer)
  1775.     {
  1776. m_pPlayer->InternalPause();     
  1777.         ReBuffer();
  1778.     }
  1779.     return;
  1780. }
  1781. BOOL
  1782. HXSource::IsRebufferRequired(void)
  1783. {
  1784.     BOOL     bResult = FALSE;
  1785.     STREAM_INFO*    pStreamInfo = NULL;
  1786.     // Check if all streams are doing OK
  1787.     for (CHXMapLongToObj::Iterator ndxStrm = mStreamInfoTable->Begin();
  1788.  ndxStrm != mStreamInfoTable->End(); ++ndxStrm) 
  1789.     {    
  1790. pStreamInfo = (STREAM_INFO*) (*ndxStrm);
  1791. if (pStreamInfo->m_unNeeded > pStreamInfo->m_unAvailable)
  1792. {
  1793.     bResult = TRUE;
  1794.     break;
  1795. }
  1796.     }
  1797.     return bResult;
  1798. }
  1799. BOOL
  1800. HXSource::IsRebufferDone(void)
  1801. {
  1802.     BOOL    bResult = TRUE;
  1803.     if (m_pSourceInfo)
  1804.     {
  1805. bResult = m_pSourceInfo->IsRebufferDone();
  1806.     }
  1807.     return bResult;
  1808. }
  1809. void
  1810. HXSource::ScheduleProcessCallback()
  1811. {
  1812.     if (m_pSourceInfo)
  1813.     {
  1814.         m_pSourceInfo->ScheduleProcessCallback();
  1815.     }
  1816. }
  1817. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  1818. /************************************************************************
  1819.  * Method:
  1820.  *     IHXHyperNavigate::GoToURL
  1821.  * Purpose:
  1822.  *     Acts as a proxy for actual hypernavigate interface.
  1823.  *     Is used to convert any relative URLs to absolute URLs
  1824.  */
  1825. STDMETHODIMP 
  1826. HXSource::GoToURL(const char* pURL, const char* pTarget)
  1827. {
  1828.     return Execute(pURL, pTarget, NULL, NULL, NULL);
  1829. }
  1830. /************************************************************************
  1831.  * Method:
  1832.  *     IHXHyperNavigate2::Execute
  1833.  * Purpose:
  1834.  *     
  1835.  * Parameters:
  1836.  *      pURL:     URL (absolute or relative)
  1837.  *     pTargetInstance:
  1838.  *     pTargetApplication: 
  1839.  *     pTargetRegion:
  1840.  *     pParams:
  1841.  */
  1842. STDMETHODIMP 
  1843. HXSource::Execute(const char* pURL,
  1844.    const char* pTargetInstance,
  1845.    const char* pTargetApplication,
  1846.    const char* pTargetRegion,
  1847.    IHXValues* pParams)
  1848. {
  1849.     HX_RESULT theErr = HXR_OK;
  1850.     CHXString newURL = pURL;
  1851. //    pURL = "rogers.rt";
  1852. //    if (pTargetInstance && 
  1853. // stricmp(pTargetInstance, "_player") == 0 &&
  1854.     if (ShouldConvert(pTargetInstance) && 
  1855. pURL  &&
  1856. strnicmp(pURL, URL_COMMAND, sizeof(URL_COMMAND) - 1) != 0 )
  1857.     {
  1858. CHXURL urlObj(pURL);
  1859. IHXValues* pHeader = urlObj.GetProperties();
  1860. IHXBuffer* pBuffer = NULL;
  1861. if(pHeader && 
  1862.    m_pszURL &&
  1863.    HXR_OK != pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer))
  1864. {
  1865.     // relative URL
  1866.     // if it starts with '/', make it relative to the root of 
  1867.     // the URL prefix
  1868.     CHXString urlPrefix, urlRoot;
  1869.     char* pURLFragment = NULL;
  1870.     theErr = CHXURL::GeneratePrefixRootFragment(m_pszURL, urlPrefix, urlRoot, pURLFragment);
  1871.     HX_VECTOR_DELETE(pURLFragment);
  1872.     if (!theErr)
  1873.     {
  1874. if(*pURL == '/')
  1875. {
  1876.     newURL = urlRoot + pURL;
  1877. }
  1878. else
  1879. {
  1880.     newURL = urlPrefix + pURL;
  1881. }
  1882.     }
  1883. }
  1884. HX_RELEASE(pBuffer);
  1885. HX_RELEASE(pHeader);
  1886.     }
  1887.     
  1888.     AddRef();
  1889.     HX_ASSERT(m_pPlayer && m_pPlayer->m_pHyperNavigate);
  1890.     if (m_pPlayer && m_pPlayer->m_pHyperNavigate)
  1891.     {
  1892. theErr = m_pPlayer->m_pHyperNavigate->ExecuteWithContext(newURL, 
  1893. pTargetInstance, pTargetApplication, pTargetRegion, 
  1894. pParams, (IUnknown*) (IHXStreamSource*) this);
  1895.     }
  1896.     Release();
  1897.     return theErr;
  1898. }
  1899. #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
  1900. STDMETHODIMP
  1901. HXSource::GetTotalBuffering(UINT16  uStreamNumber,
  1902.     REF(INT64)  llLowestTimestamp, 
  1903.     REF(INT64)  llHighestTimestamp,
  1904.     REF(UINT32) ulNumBytes,
  1905.     REF(BOOL)   bDone)
  1906. {
  1907.     HX_RESULT res = HXR_NO_DATA;
  1908.     
  1909.     llLowestTimestamp = 0;
  1910.     llHighestTimestamp = 0;
  1911.     ulNumBytes = 0;
  1912.     bDone = FALSE;
  1913.     STREAM_INFO* pStreamInfo;
  1914.     if (mStreamInfoTable->Lookup((LONG32) uStreamNumber, (void*& )pStreamInfo))
  1915.     {
  1916. HXBufferingState& bufState = pStreamInfo->BufferingState();
  1917. BOOL   bUseTransportStats = FALSE;
  1918. INT64  llTransportLowTS = 0;
  1919. INT64  llTransportHighTS = 0;
  1920. UINT32 ulTransportBytes = 0;
  1921. BOOL   bTransportDone = FALSE;
  1922. if (!IsLocalSource() &&
  1923.     (HXR_OK == GetCurrentBuffering(uStreamNumber,
  1924.    llTransportLowTS,
  1925.    llTransportHighTS,
  1926.    ulTransportBytes,
  1927.    bTransportDone)))
  1928. {
  1929.     bufState.UpdateTransportStats(llTransportLowTS,
  1930.   llTransportHighTS,
  1931.   ulTransportBytes,
  1932.   bTransportDone);
  1933.     bUseTransportStats = TRUE;
  1934.     // Update bDone with what the transport says.
  1935.     bDone = bTransportDone;
  1936. }
  1937. res = bufState.GetBufferingStats(llLowestTimestamp,
  1938.  llHighestTimestamp,
  1939.  ulNumBytes,
  1940.  bUseTransportStats);
  1941.     }
  1942.     return res;
  1943. }
  1944. /* 
  1945.  * All relative URLs are converted to absolute URLs unless the 
  1946.  * original request (ram/smil) passed in OpenRequest/OpenURL()
  1947.  * is a mem: URL AND the target is not _player.
  1948.  *
  1949.  * This fixes relative URLs being hurled to the browser using events
  1950.  * come from the same location as the .ram file. (Broadcase usage case)
  1951.  * PR 31352
  1952.  *
  1953.  * This also fixes content on CD-ROMs where relative URLs being hurled 
  1954.  * to the browser using events come from the same location as 
  1955.  * the .rm file in which they are merged. 
  1956.  * PR 23489
  1957.  */
  1958. BOOL HXSource::ShouldConvert(const char* pTargetInstance)
  1959. {
  1960.     if (pTargetInstance && 
  1961. stricmp(pTargetInstance, "_player") == 0)
  1962.     {
  1963. return TRUE;
  1964.     }
  1965.     
  1966.     const char* pPlayerURL = NULL;
  1967.     IHXRequest* pPlayerRequest = NULL;
  1968.     if (m_pPlayer)
  1969.     {
  1970. m_pPlayer->GetRequest(pPlayerRequest);
  1971. if (pPlayerRequest)
  1972. {
  1973.     pPlayerRequest->GetURL(pPlayerURL);
  1974. }
  1975.     }
  1976.     HX_RELEASE(pPlayerRequest);
  1977.     if (pPlayerURL && ::strncasecmp(pPlayerURL, "mem:", 4) == 0)
  1978.     {
  1979. return FALSE;
  1980.     }
  1981.     return TRUE;
  1982. }
  1983. void
  1984. HXSource::MergeUpgradeRequest(BOOL bAddDefault /*= FALSE*/, char* pUpgradeString /* = NULL*/)
  1985. {
  1986. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  1987.     if (m_pPlayer && 
  1988. bAddDefault && 
  1989. (!m_pUpgradeCollection || m_pUpgradeCollection->GetCount() == 0))
  1990.     {
  1991. if (!m_pUpgradeCollection)
  1992. {
  1993.     m_pUpgradeCollection = new HXUpgradeCollection;
  1994. }
  1995. if (!pUpgradeString)
  1996. {
  1997.     pUpgradeString = "Missing Component";
  1998. }
  1999. IHXBuffer* pPluginID = (IHXBuffer*) new CHXBuffer;
  2000. pPluginID->AddRef();
  2001. pPluginID->Set((const UINT8*)pUpgradeString, strlen(pUpgradeString) + 1);
  2002. m_pUpgradeCollection->Add(eUT_Required, pPluginID, 0, 0);
  2003. pPluginID->Release();
  2004.     }
  2005.     if (m_pPlayer && m_pUpgradeCollection && m_pUpgradeCollection->GetCount() > 0)
  2006.     {
  2007. UINT32 ulCount = m_pUpgradeCollection->GetCount();
  2008. IHXUpgradeCollection* pPlayerUpgrade;
  2009. m_pPlayer->QueryInterface(IID_IHXUpgradeCollection, (void**) &pPlayerUpgrade);
  2010. for (UINT32 i = 0; i < ulCount; i++)
  2011. {
  2012.     HXUpgradeType upgradeType;
  2013.     IHXBuffer* pPluginId = (IHXBuffer*) new CHXBuffer;
  2014.     UINT32 majorVersion;
  2015.     UINT32 minorVersion;
  2016.     pPluginId->AddRef(); 
  2017.     // GetAt is a non-COM like API. It expects pPluginID to be allocated by the user
  2018.     // and does not perform an addref either!
  2019.     m_pUpgradeCollection->GetAt(i, upgradeType, pPluginId, majorVersion, minorVersion);
  2020.     pPlayerUpgrade->Add(upgradeType, pPluginId, majorVersion, minorVersion);
  2021.     pPluginId->Release();
  2022. }
  2023. pPlayerUpgrade->Release();
  2024. m_pUpgradeCollection->RemoveAll();
  2025.     }
  2026. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  2027. }
  2028. void
  2029. HXSource::ClearUpgradeRequest()
  2030. {
  2031. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  2032.     if (m_pUpgradeCollection)
  2033.     {
  2034. m_pUpgradeCollection->RemoveAll();
  2035.     }
  2036. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  2037. }
  2038. void
  2039. HXSource::EnterPrefetch(PrefetchType prefetchType, UINT32 ulPrefetchValue)
  2040. {
  2041.     m_bPrefetch = TRUE;
  2042.     m_prefetchType = prefetchType;
  2043.     m_ulPrefetchValue = ulPrefetchValue;
  2044.     return;
  2045. }
  2046. void
  2047. HXSource::LeavePrefetch(void)
  2048. {
  2049.     m_bPrefetch = FALSE;
  2050.     // send prefetch notification so that SMIL
  2051.     // renderer can resolve the duration on this prefetch track
  2052.     if (m_pSourceInfo)
  2053.     {
  2054. m_pPlayer->PrefetchTrackDone(m_pSourceInfo->m_uGroupID, 
  2055.           m_pSourceInfo->m_uTrackID, 
  2056.      HXR_OK);
  2057.     }
  2058.     return;
  2059. }
  2060. void
  2061. HXSource::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice)
  2062. {
  2063. #if defined(HELIX_FEATURE_SMIL_SOUNDLEVEL)
  2064.     CHXAudioPlayer* pAudioPlayer = NULL;
  2065.     CHXAudioStream* pCHXAudioStream = NULL;
  2066.     CHXSimpleList*  pAudioStreamList = NULL;
  2067.     if (!m_pPlayer)
  2068.     {
  2069. goto cleanup;
  2070.     }
  2071.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  2072.     if (!pAudioPlayer)
  2073.     {
  2074. goto cleanup;
  2075.     }
  2076.     pAudioPlayer->AddRef();
  2077.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  2078.     {
  2079. pAudioPlayer->SetSoundLevel(pAudioStreamList, uSoundLevel, bReflushAudioDevice);
  2080. ReleaseAudioStreams(pAudioStreamList);
  2081. HX_DELETE(pAudioStreamList);
  2082.     }
  2083.     HX_RELEASE(pAudioPlayer);
  2084. cleanup:
  2085. #endif /* HELIX_FEATURE_SMIL_SOUNDLEVEL */
  2086.     return;
  2087. }
  2088. void
  2089. HXSource::SetAudioDeviceReflushHint(void)
  2090. {
  2091. #if defined(HELIX_FEATURE_SOUNDLEVEL)
  2092.     CHXAudioPlayer* pAudioPlayer = NULL;
  2093.     CHXSimpleList*  pAudioStreamList = NULL;
  2094.     if (!m_pPlayer)
  2095.     {
  2096. goto cleanup;
  2097.     }
  2098.     pAudioPlayer = m_pPlayer->GetAudioPlayer();
  2099.     if (!pAudioPlayer)
  2100.     {
  2101. goto cleanup;
  2102.     }
  2103.     pAudioPlayer->AddRef();
  2104.     if (HXR_OK == CollectAudioStreams(pAudioStreamList) && pAudioStreamList)
  2105.     {
  2106. pAudioPlayer->ManageAudioStreams(pAudioStreamList, CHXAudioPlayer::STR_SETHINT);
  2107. ReleaseAudioStreams(pAudioStreamList);
  2108. HX_DELETE(pAudioStreamList);
  2109.     }
  2110.     HX_RELEASE(pAudioPlayer);
  2111. cleanup:
  2112. #endif /* HELIX_FEATURE_SOUNDLEVEL */
  2113.     return;
  2114. }
  2115. void
  2116. HXSource::LeaveFastStart(TurboPlayOffReason leftReason)
  2117. {
  2118.     m_turboPlayStats.tpOffReason = leftReason;
  2119.     m_bFastStart = FALSE;
  2120. }
  2121. void
  2122. HXSource::DeleteAllEvents()
  2123. {
  2124.     if (m_PacketBufferList.GetCount() > 0)
  2125.     {
  2126. LISTPOSITION pos = m_PacketBufferList.GetHeadPosition();
  2127. while (pos != NULL)
  2128. {
  2129.     CHXEvent* pTempEvent  = (CHXEvent*) m_PacketBufferList.GetNext(pos);
  2130.     delete pTempEvent;
  2131. }
  2132. m_PacketBufferList.RemoveAll();
  2133.     }
  2134. }
  2135. void
  2136. HXSource::SetMinimumPreroll(ULONG32 ulMinimumAudioPreroll, ULONG32 ulMinimumStartingPreroll)
  2137. {
  2138.     UINT32 ulTotalMinimumPreroll = 0;
  2139.     if (m_pPlayer)
  2140.     {
  2141. // get the user-set minimum preroll
  2142. m_pPlayer->GetMinimumPreroll(ulTotalMinimumPreroll);
  2143.     }
  2144.     if (IsAnyAudioStream())
  2145.     {
  2146. m_ulPreRollInMs += ulMinimumAudioPreroll;
  2147.     }
  2148.     if (m_ulPreRollInMs < ulTotalMinimumPreroll)
  2149.     {
  2150. m_ulPreRollInMs = ulTotalMinimumPreroll;
  2151.     }
  2152.     DEBUG_OUT(m_pPlayer, DOL_TRANSPORT, (s, "(%p)Preroll: %lu MinPreroll %lu MinAudioPreroll %lu", this, m_ulPreRollInMs, ulTotalMinimumPreroll, ulMinimumStartingPreroll));
  2153.     m_pBufferManager->SetMinimumPreroll(IsLocalSource() | m_bPerfectPlay,
  2154. ulTotalMinimumPreroll,
  2155. ulMinimumStartingPreroll);
  2156. }
  2157. HX_RESULT
  2158. HXSource::SendHeaderToRecordControl(BOOL bFileHeader, IHXValues* pHeader)
  2159. {
  2160. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2161.     HX_RESULT nResult = HXR_OK;
  2162.     if(m_pRecordControl && pHeader)
  2163.     {
  2164. if(bFileHeader)
  2165.     nResult = m_pRecordControl->OnFileHeader(pHeader);
  2166. else
  2167.     nResult = m_pRecordControl->OnStreamHeader(pHeader);
  2168. if(nResult != HXR_OK)
  2169. {
  2170.     m_bPlayFromRecordControl = FALSE;
  2171.     if(nResult != HXR_RECORD)
  2172. HX_RELEASE(m_pRecordControl);
  2173. }
  2174.     }
  2175.     return nResult;
  2176. #else
  2177.     return HXR_NOTIMPL;
  2178. #endif /* HELIX_FEATURE_RECORDCONTROL */
  2179. }
  2180. void
  2181. HXSource::ProcessFileHeader(void)
  2182. {
  2183.     UINT32      bNonSeekAble = 0;
  2184.     IHXBuffer*  pTitle = NULL;
  2185.     IHXBuffer*  pAuthor = NULL;
  2186.     IHXBuffer*  pCopyright = NULL;
  2187.     IHXBuffer*  pAbstract = NULL;
  2188.     IHXBuffer*  pDescription = NULL;
  2189.     IHXBuffer*  pKeywords = NULL;
  2190.     IHXValues*  pValues = NULL;
  2191.     if (m_pURL)
  2192.     {
  2193. pValues = m_pURL->GetOptions();
  2194.     }
  2195.     // retrieve the TAC from the URL
  2196.     if (pValues)
  2197.     {
  2198. pValues->GetPropertyBuffer("Title", pTitle);
  2199.         pValues->GetPropertyBuffer("Author", pAuthor);
  2200.         pValues->GetPropertyBuffer("Copyright", pCopyright);
  2201.         pValues->GetPropertyBuffer("Abstract", pAbstract);
  2202.         pValues->GetPropertyBuffer("Description", pDescription);
  2203.         pValues->GetPropertyBuffer("Keywords", pKeywords);
  2204. //#define LOSS_HACK
  2205. #ifdef LOSS_HACK
  2206. UINT32 ulLoss = 0;
  2207. if (HXR_OK == pValues->GetPropertyULONG32("Loss", ulLoss))
  2208. {
  2209.     m_ulLossHack = ulLoss;
  2210.     /* Initialize random number generator */
  2211.     ::srand((unsigned int) HX_GET_TICKCOUNT());
  2212. }
  2213. #endif /*LOSS_HACK*/
  2214.     }
  2215.     if (m_pFileHeader)
  2216.     {
  2217.         if (!pTitle)     m_pFileHeader->GetPropertyBuffer("Title", pTitle);
  2218.         if (!pAuthor)     m_pFileHeader->GetPropertyBuffer("Author", pAuthor);
  2219.         if (!pCopyright)    m_pFileHeader->GetPropertyBuffer("Copyright", pCopyright);
  2220.         if (!pDescription)  m_pFileHeader->GetPropertyCString("Description", pDescription);
  2221.         if (!pAbstract)     m_pFileHeader->GetPropertyCString("Abstract", pAbstract);
  2222.         if (!pKeywords)     m_pFileHeader->GetPropertyCString("Keywords", pKeywords);
  2223.         m_pFileHeader->GetPropertyULONG32("NonSeekable", bNonSeekAble);
  2224. m_bNonSeekable = bNonSeekAble ? TRUE : FALSE;
  2225.         
  2226.         m_pFileHeader->GetPropertyULONG32("StreamCount",m_ulStreamHeadersExpected);
  2227.             
  2228.         HX_ASSERT(mStreamInfoTable->IsEmpty() == TRUE);
  2229.         if (mStreamInfoTable->IsEmpty() && m_ulStreamHeadersExpected > 0 &&
  2230.             m_ulStreamHeadersExpected < mStreamInfoTable->GetHashTableSize())
  2231.         {
  2232.             mStreamInfoTable->InitHashTable(m_ulStreamHeadersExpected);
  2233.         }
  2234.     }
  2235. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2236.     if (m_pStats)
  2237.     {
  2238.         if (pTitle && m_pStats->m_pTitle)
  2239.         {
  2240.     m_pStats->m_pTitle->SetStr((char*)(pTitle->GetBuffer()));
  2241.         }
  2242.         if (pAuthor && m_pStats->m_pAuthor)
  2243.         {
  2244.     m_pStats->m_pAuthor->SetStr((char*)(pAuthor->GetBuffer()));
  2245.         }
  2246.         if (pCopyright && m_pStats->m_pCopyright)
  2247.         {
  2248.     m_pStats->m_pCopyright->SetStr((char*)(pCopyright->GetBuffer()));
  2249.         }
  2250.         if (pAbstract && m_pStats->m_pAbstract)
  2251.         {
  2252.     m_pStats->m_pAbstract->SetStr((char*)(pAbstract->GetBuffer()));
  2253.         }
  2254.     
  2255.         if (pDescription && m_pStats->m_pDescription)
  2256.         {
  2257.             m_pStats->m_pDescription->SetStr((char*)(pDescription->GetBuffer()));
  2258.         }
  2259.         if (pKeywords && m_pStats->m_pKeywords)
  2260.         {
  2261.     m_pStats->m_pKeywords->SetStr((char*)(pKeywords->GetBuffer()));
  2262.         }
  2263.     }
  2264.     CopyMetaDataToRegistry(m_pFileHeader);
  2265. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2266.     m_bReceivedHeader = TRUE;
  2267.     HX_RELEASE(pTitle);
  2268.     HX_RELEASE(pAuthor);
  2269.     HX_RELEASE(pCopyright);
  2270.     HX_RELEASE(pAbstract);
  2271.     HX_RELEASE(pDescription);
  2272.     HX_RELEASE(pKeywords);
  2273.     HX_RELEASE(pValues);
  2274.     return;
  2275. }
  2276. static BOOL GetHeaderBOOL(IHXValues* pHeader, const char* pKey)
  2277. {
  2278.     BOOL bRet = FALSE;
  2279.     ULONG32 ulTemp = 0;
  2280.     if ((HXR_OK == pHeader->GetPropertyULONG32(pKey, ulTemp)) && ulTemp)
  2281.     {
  2282. bRet = TRUE;
  2283.     }
  2284.     return bRet;
  2285. }
  2286. HX_RESULT
  2287. HXSource::ProcessStreamHeaders(IHXValues* pHeader, STREAM_INFO*& pStreamInfo)
  2288. {
  2289.     HX_RESULT       rc = HXR_OK;
  2290.     UINT32          ulStreamNumber = 0;
  2291.     UINT32          ulAvgBitRate = 0;
  2292.     UINT32          ulAvgPacketSize = 0;
  2293.     UINT32          ulPreroll = 0;
  2294.     ULONG32         ulPredata = 0;
  2295.     UINT32          ulDuration = 0;
  2296.     UINT32          ulTemp = 0;
  2297.     void*           lTmp = NULL;
  2298.     pStreamInfo = NULL;
  2299.     if (!pHeader)
  2300.     {
  2301.         rc = HX_INVALID_HEADER;
  2302.         goto cleanup;
  2303.     }
  2304.     // Use file header for default duration
  2305.     if (m_pFileHeader)
  2306.     {
  2307.         m_pFileHeader->GetPropertyULONG32("Duration", ulDuration);
  2308.         if (!m_ulDuration && ulDuration)
  2309.         {
  2310.             m_ulDuration = ulDuration;
  2311.             ulDuration = 0;
  2312.         }
  2313.     }
  2314.     pHeader->GetPropertyULONG32("StreamNumber",     ulStreamNumber);
  2315.     pHeader->GetPropertyULONG32("AvgBitRate",     ulAvgBitRate);
  2316.     pHeader->GetPropertyULONG32("AvgPacketSize",    ulAvgPacketSize);
  2317.     pHeader->GetPropertyULONG32("Preroll",     ulPreroll);
  2318.     pHeader->GetPropertyULONG32("Predata",          ulPredata);
  2319.     pHeader->GetPropertyULONG32("Duration",     ulDuration);
  2320.     if (mStreamInfoTable->Lookup((LONG32) ulStreamNumber, (void *&) lTmp))
  2321.     {
  2322. // a header with this stream number already exists..
  2323.         rc = HX_INVALID_HEADER;
  2324.         goto cleanup;
  2325.     }
  2326.     // max preroll
  2327.     if (m_ulPreRollInMs < ulPreroll)
  2328.     {
  2329. m_ulPreRollInMs = ulPreroll;
  2330.     }
  2331.     m_ulAvgBandwidth   += ulAvgBitRate;
  2332.     // max duration...
  2333.     if (m_ulDuration < ulDuration)
  2334.     {
  2335. m_ulDuration = ulDuration;
  2336.     }
  2337.     pStreamInfo = new STREAM_INFO;
  2338.     if (!pStreamInfo)
  2339.     {
  2340. rc = HXR_OUTOFMEMORY;
  2341.         goto cleanup;
  2342.     }
  2343.     pStreamInfo->m_pHeader                  = pHeader;
  2344.     pStreamInfo->m_pHeader->AddRef();
  2345.     pStreamInfo->m_bCustomEndTime           = FALSE;
  2346.     pStreamInfo->m_bSrcStreamDone           = FALSE;
  2347.     pStreamInfo->m_bSrcStreamFillingDone    = FALSE;
  2348.     pStreamInfo->m_bPacketRequested         = FALSE;
  2349.     
  2350.     pStreamInfo->m_uStreamNumber = (UINT16) ulStreamNumber;
  2351.     pStreamInfo->m_ulDuration = ulDuration;
  2352.     pStreamInfo->BufferingState().OnStreamHeader(
  2353. ulPreroll,
  2354. ulPredata,
  2355. GetHeaderBOOL(pHeader, "PreDataAtStart"),
  2356. GetHeaderBOOL(pHeader, "PreDataAfterSeek"),
  2357. GetHeaderBOOL(pHeader, "PrerollAtStart"),
  2358. GetHeaderBOOL(pHeader, "PrerollAfterSeek"),
  2359. ulAvgBitRate);
  2360.     mStreamInfoTable->SetAt(ulStreamNumber, (void *) pStreamInfo);
  2361. cleanup:
  2362.     return rc;
  2363. }
  2364. HX_RESULT HXSource::OnTimeSync(ULONG32 ulCurrentTime)
  2365. {
  2366.     HX_RESULT res = HXR_OK;
  2367.     for (CHXMapLongToObj::Iterator i = mStreamInfoTable->Begin();
  2368.          i != mStreamInfoTable->End(); ++i) 
  2369.     {    
  2370. STREAM_INFO* pStreamInfo = (STREAM_INFO*) (*i);
  2371. pStreamInfo->BufferingState().OnTimeSync(ulCurrentTime);
  2372.     }
  2373.     return res;
  2374. }