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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: srcinfo.cpp,v 1.26.2.3 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. #include "hxresult.h"
  52. #include "smiltype.h"
  53. #include "hxcomm.h" // IHXRegistryID
  54. #include "hxengin.h"
  55. #include "hxcore.h"
  56. #include "hxupgrd.h"
  57. #include "hxrendr.h"
  58. #include "hxasm.h"
  59. #include "hxsmbw.h"
  60. #include "hxgroup.h"
  61. #include "hxausvc.h"
  62. #include "hxslist.h"
  63. #include "hxmap.h"
  64. #include "chxpckts.h"
  65. #include "chxeven.h"
  66. #include "chxelst.h"
  67. #include "strminfo.h"
  68. #include "timeval.h"
  69. #include "hxbsrc.h"
  70. #include "hxsrc.h"
  71. #include "hxstrm.h"
  72. #include "hxsmstr.h"
  73. #include "hxaudply.h"
  74. #include "basgroup.h"
  75. #include "advgroup.h"
  76. #include "hxthread.h"
  77. #include "hxtick.h"
  78. #include "hxstrutl.h"
  79. #include "srcinfo.h"
  80. #include "hxplay.h"
  81. #include "hxcleng.h"
  82. #include "plghand2.h"
  83. #include "hxheap.h"
  84. #ifdef _DEBUG
  85. #undef HX_THIS_FILE
  86. static const char HX_THIS_FILE[] = __FILE__;
  87. #endif
  88. #define TIME_SYNC_FUDGE_FACTOR      10
  89. #define GOTOEXITONERROR(theErr, label)      if ((theErr) != 0) goto label
  90. SourceInfo::SourceInfo(HXPlayer* pPlayer)
  91. {
  92.     m_pRendererMap = new CHXMapLongToObj;
  93.     
  94.     m_pPlayer = pPlayer;
  95.     m_pPlayer->AddRef();
  96.     m_pSource     = NULL;
  97.     m_bDone     = FALSE;
  98.     m_bStopped     = FALSE;
  99.     m_bInitialized     = FALSE;
  100.     m_pStatus     = NULL;
  101.     m_bAllPacketsReceived   = FALSE;
  102.     m_bActive     = TRUE;
  103.     m_bIsPersistentSource   = FALSE;
  104.     m_bIsRegisterSourceDone = FALSE;
  105.     m_uTrackID     = 0;
  106.     m_uGroupID     = 0;
  107.     m_bToBeResumed     = TRUE;
  108.     m_bAreStreamsSetup     = FALSE;
  109.     m_bTrackStartedToBeSent = TRUE;
  110.     m_bTrackStoppedToBeSent = TRUE;
  111.     m_bPrefetch     = FALSE;
  112.     m_bLoadPluginAttempted  = FALSE;
  113.     m_pCurrentScheduleList  = NULL;
  114.     m_ulSourceDuration     = 0;
  115.     m_ulMaxDuration     = 0;
  116.     m_ulTrackDuration     = 0;
  117.     m_ulTotalTrackDuration  = 0;
  118.     m_pDependNode     = NULL;
  119.     m_uNumDependencies     = 0;
  120.     m_bTobeInitializedBeforeBegin = FALSE;
  121.     m_bAltURL     = FALSE;
  122.     m_lastErrorFromMainURL  = HXR_OK;
  123.     m_lastError             = HXR_OK;
  124.     m_bLocked     = FALSE;
  125.     m_bIsTrackDurationSet   = FALSE;
  126.     m_bDurationTimeSyncScheduled = FALSE;
  127.     m_bAudioDeviceReflushHint = FALSE;
  128.     m_pProcessCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)ProcessCallback);
  129.     m_pProcessCallback->AddRef();
  130.     m_prefetchType = PrefetchUnknown;
  131.     m_ulPrefetchValue = 0;
  132.     m_uSoundLevel = 100;
  133.     m_fillType = FillRemove;
  134.     m_pPeerSourceInfo = NULL;   
  135.     m_bSeekPending = FALSE;
  136.     m_bIndefiniteDuration = FALSE;
  137.     m_bRepeatIndefinite = FALSE;
  138.     m_bSeekToLastFrame = FALSE;
  139.     m_ulRepeatInterval = 0;
  140.     m_ulRepeatDelayTimeOffset = 0;
  141.     m_ulSeekTime = 0;
  142.     m_ulPausedStartTime = 0;
  143.     m_bLeadingSource = TRUE;
  144.     m_bRepeatPending = FALSE;
  145.     m_pRepeatList = NULL;
  146.     m_curPosition = 0;
  147.     
  148.     m_ulPersistentComponentID = MAX_UINT32;
  149.     m_ulPersistentComponentSelfID = MAX_UINT32;
  150.     m_pRendererAdviseSink = NULL;
  151. #ifdef THREADS_SUPPORTED
  152.     HXMutex::MakeMutex(m_pMutex);
  153. #else
  154.     HXMutex::MakeStubMutex(m_pMutex);
  155. #endif
  156.     /*
  157.      * The following members are needed for live sync support.
  158.      */
  159.     m_pWallClock = NULL;
  160.     m_ulStreamStartTime = 0;
  161.     m_llLatestPacketTime    = 0;
  162. }
  163. SourceInfo::~SourceInfo()
  164. {
  165.     if (m_pProcessCallback && m_pPlayer->m_pScheduler)
  166.     {
  167. m_pPlayer->m_pScheduler->Remove(m_pProcessCallback->GetPendingCallback());
  168.         m_pProcessCallback->CallbackCanceled();
  169.     }
  170.     if (m_pRepeatList)
  171.     {
  172. while (m_pRepeatList->GetCount())
  173. {
  174.     RepeatInfo* pRepeatInfo = (RepeatInfo*)m_pRepeatList->RemoveHead();
  175.     HX_DELETE(pRepeatInfo);
  176. }
  177. HX_DELETE(m_pRepeatList);
  178.     }
  179.     HX_RELEASE(m_pStatus);
  180.     HX_RELEASE(m_pProcessCallback);
  181.     HX_RELEASE(m_pPlayer);
  182.     HX_DELETE(m_pCurrentScheduleList);
  183.     HX_VECTOR_DELETE(m_pDependNode);
  184.     HX_DELETE(m_pMutex);
  185.     HX_DELETE(m_pRendererMap);
  186.     /*
  187.      * For live sync support, we may have used a shared wall
  188.      * clock, if so then we're done with it now, so we may need 
  189.      * to do some cleanup work here.     
  190.      */
  191.     DoneWithWallClock();
  192. };
  193. HX_RESULT
  194. SourceInfo::Begin()
  195. {
  196.     HX_RESULT theErr = HXR_OK;
  197.     if(!m_pSource || !m_pSource->IsInitialized())
  198.     {
  199. return HXR_OK;
  200.     }
  201.     if (m_pPlayer->m_bInitialized)
  202.     {
  203. // handle the seek so that the server will be notified 
  204. // via the play request upon the first resume
  205. if (m_bSeekPending)
  206. {
  207.     m_bSeekPending = FALSE;
  208.     Pause();
  209.     Seek(m_ulSeekTime);
  210.     m_pSource->DoSeek(m_ulSeekTime);
  211. }
  212. theErr = m_pSource->DoResume();
  213.     }
  214.     if (!m_bInitialized)
  215.     {
  216. return HXR_OK;
  217.     }
  218.     /* Only send this OnBegin()'s if not the first begin. In the case
  219.      * of the first begin, these are actually sent after the header's
  220.      * arrive...
  221.      */
  222.     if (!m_pPlayer->m_bIsFirstBegin && !m_pPlayer->m_bInternalPauseResume)
  223.     {
  224. CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  225. for (; !theErr &&
  226. ndxRend != m_pRendererMap->End(); ++ndxRend)
  227. {
  228.     RendererInfo* pRendInfo = (RendererInfo*) (*ndxRend);
  229.     if (!pRendInfo->m_bInitialBeginToBeSent)
  230.     {
  231. IHXRenderer* pRend  = (IHXRenderer*) pRendInfo->m_pRenderer;
  232. pRend->OnBegin(m_pPlayer->m_ulCurrentPlayTime);
  233.     }
  234. }
  235.     }
  236.     return theErr;
  237. }
  238. HX_RESULT
  239. SourceInfo::Pause()
  240. {
  241.     HX_RESULT theErr = HXR_OK;
  242.     if(!m_pSource)
  243.     {
  244. return HXR_OK;
  245.     }
  246.     theErr = m_pSource->DoPause();
  247.     /* Do not send OnPause to renderers if it is an internal Pause */
  248.     if (m_pPlayer->m_bInternalPauseResume || !m_bInitialized)
  249.     {
  250. return theErr;
  251.     }
  252.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  253.     for (; !theErr &&
  254.     ndxRend != m_pRendererMap->End(); ++ndxRend)
  255.     {
  256. RendererInfo* pRendInfo = (RendererInfo*) (*ndxRend);
  257. IHXRenderer* pRend     = (IHXRenderer*) pRendInfo->m_pRenderer;
  258. m_pPlayer->m_pScheduler->Remove(
  259.          pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
  260.         
  261.         pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
  262. pRendInfo->m_bIsFirstCallback   = TRUE;
  263. pRend->OnPause(m_pPlayer->m_ulCurrentPlayTime);
  264.     }
  265.     return theErr;
  266. }
  267. HX_RESULT
  268. SourceInfo::Seek(UINT32 ulSeekTo)
  269. {
  270.     HX_RESULT     rc = HXR_OK;
  271.     INT64     llLastExpectedPacketTime = 0;
  272.     BOOL     bSeekToLastFrame = FALSE;
  273.     BOOL     bDurationTimeSyncSent = TRUE;
  274.     UINT32     ulValue = 0;
  275.     RendererInfo*     pRendInfo = NULL;
  276.     STREAM_INFO*     pStreamInfo = NULL;
  277.     IHXValues*     pStatus = NULL;
  278.     IHXPersistentRenderer*     pPersRender = NULL;
  279.     IHXPersistentComponent*     pPersComp = NULL;
  280.     HXPersistentComponentManager*  pPersCompMgr = NULL;
  281.     CHXMapLongToObj::Iterator ndx;
  282.     /* m_pSource should never be NULL */
  283.     HX_ASSERT(m_pSource);
  284.     if(!m_pSource || !m_bInitialized)
  285.     {
  286. return HXR_OK;
  287.     }
  288.     m_bDone = FALSE;
  289.     m_bActive = TRUE;
  290.     m_bAllPacketsReceived = FALSE;
  291.     llLastExpectedPacketTime = m_pSource->GetLastExpectedPacketTime();
  292.     /* Are we seeking past the last expected packet time?
  293.      * If so, verify the "show" attribute to see whether we need to
  294.      * get the last video frame
  295.      */    
  296.     if (!m_pSource->IsLive() && ulSeekTo >= INT64_TO_UINT32(llLastExpectedPacketTime + m_pSource->GetDelay()))
  297.     {
  298. #if defined(HELIX_FEATURE_NESTEDMETA)
  299. pPersCompMgr = m_pPlayer->m_pPersistentComponentManager;
  300. if (FillFreeze == m_fillType && pPersCompMgr) 
  301. {
  302.     rc = pPersCompMgr->GetPersistentComponent(m_ulPersistentComponentID,
  303.       pPersComp);
  304.     HX_ASSERT(HXR_OK == rc);
  305.     if (pPersComp)
  306.     {
  307. rc = pPersComp->GetPersistentRenderer(pPersRender);
  308. HX_ASSERT(HXR_OK == rc);
  309. rc = pPersRender->GetElementStatus(m_uGroupID,
  310.    m_uTrackID,
  311.    ulSeekTo,
  312.    pStatus);
  313. HX_ASSERT(HXR_OK == rc);
  314. if (pStatus && HXR_OK == pStatus->GetPropertyULONG32("Show", ulValue))
  315. {
  316.     bSeekToLastFrame = (BOOL)ulValue;
  317. }
  318. HX_RELEASE(pStatus);
  319. HX_RELEASE(pPersRender);
  320. HX_RELEASE(pPersComp);
  321.     }
  322. }
  323. else if (FillHold == m_fillType)
  324. {
  325.     bSeekToLastFrame = TRUE;
  326. }
  327. #else
  328. if (FillHold == m_fillType)
  329. {
  330.     bSeekToLastFrame = TRUE;
  331. }
  332. #endif /* HELIX_FEATURE_NESTEDMETA */
  333.     }
  334.     // also check if we already sent OnTimeSync() upon its duration ends
  335.     // which means the renderer got the last frame so we don't need to issue
  336.     // last frame seek
  337.     if (bSeekToLastFrame)
  338.     {
  339. ndx = m_pRendererMap->Begin();
  340. for (; ndx != m_pRendererMap->End(); ++ndx)
  341. {
  342.     pRendInfo = (RendererInfo*)(*ndx);
  343.     if (!pRendInfo->m_bDurationTimeSyncSent)
  344.     {
  345. bDurationTimeSyncSent = FALSE;
  346.     }
  347. }
  348. if (bDurationTimeSyncSent)
  349. {
  350.     bSeekToLastFrame = FALSE;
  351. }
  352.     }
  353.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  354.     for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  355.     {
  356. RendererInfo* pRendInfo     = (RendererInfo*)(*ndxRend);
  357. IHXRenderer* pRend         = (IHXRenderer*)pRendInfo->m_pRenderer;
  358. STREAM_INFO*  pStreamInfo   = pRendInfo->m_pStreamInfo;
  359. pStreamInfo->m_bSrcInfoStreamDone  = FALSE;
  360. pRendInfo->m_pStream->ResetASMRuleState();
  361. pStreamInfo->ResetPostEndTimeEventList();
  362. if (m_pSource->IsLive())
  363. {
  364. #if defined(HELIX_FEATURE_RECORDCONTROL)
  365.     if(m_pSource->IsPlayingFromRecordControl())
  366.     {
  367. pStreamInfo->m_ulTimeBeforeSeek = m_pPlayer->m_ulTimeBeforeSeek;
  368. pStreamInfo->m_ulTimeAfterSeek = m_pPlayer->m_ulTimeAfterSeek;
  369. if (pRendInfo->m_bTimeDiffPositive)
  370. {
  371.     pStreamInfo->m_ulTimeBeforeSeek += pRendInfo->m_ulTimeDiff;
  372.     pStreamInfo->m_ulTimeAfterSeek += pRendInfo->m_ulTimeDiff;
  373. }
  374. else
  375. {
  376.     pStreamInfo->m_ulTimeBeforeSeek -= pRendInfo->m_ulTimeDiff;
  377.     pStreamInfo->m_ulTimeAfterSeek -= pRendInfo->m_ulTimeDiff;
  378. }
  379.     }
  380.     else
  381. #endif /* HELIX_FEATURE_RECORDCONTROL */
  382.     {
  383. UINT32 ulLastTimeSync = (LONG32) m_pPlayer->m_ulLiveSeekTime;
  384. if (pRendInfo->m_bTimeDiffPositive)
  385. {
  386.     ulLastTimeSync += pRendInfo->m_ulTimeDiff;
  387. }
  388. else
  389. {
  390.     ulLastTimeSync -= pRendInfo->m_ulTimeDiff;
  391. }
  392. pStreamInfo->m_ulTimeBeforeSeek = ulLastTimeSync;
  393. pStreamInfo->m_ulTimeAfterSeek  = ulLastTimeSync + m_pPlayer->m_ulElapsedPauseTime;
  394.     }
  395. }
  396. else
  397. {
  398.     pStreamInfo->m_ulTimeBeforeSeek = m_pPlayer->m_ulTimeBeforeSeek;
  399.     if (bSeekToLastFrame)
  400.     {
  401. HX_ASSERT(llLastExpectedPacketTime + m_pSource->GetDelay() >= 1);
  402. pStreamInfo->m_ulTimeAfterSeek = INT64_TO_UINT32(llLastExpectedPacketTime + m_pSource->GetDelay() - 1);
  403.     }
  404.     else
  405.     {
  406. pStreamInfo->m_ulTimeAfterSeek = m_pPlayer->m_ulTimeAfterSeek;
  407.     }
  408. }
  409. pRend->OnPreSeek(pStreamInfo->m_ulTimeBeforeSeek,
  410.  pStreamInfo->m_ulTimeAfterSeek);
  411. pStreamInfo->m_pStream->m_bPostSeekToBeSent = TRUE;
  412. // reset renderer info attributes 
  413. pRendInfo->m_ulLatestEventTime     = 0;
  414. pRendInfo->m_bIsFirstCallback     = TRUE;
  415. pRendInfo->m_ulLastSyncTime         = 0;
  416. pRendInfo->m_ulNextDueSyncTime      = m_pPlayer->m_ulCurrentPlayTime;
  417. /* Do we need to send a time sync for renderer duration? */
  418. if (bSeekToLastFrame || pRendInfo->m_ulNextDueSyncTime <= pRendInfo->m_ulDuration)
  419. {
  420.     pRendInfo->m_bDurationTimeSyncSent  = FALSE;
  421.     pRendInfo->m_bOnEndOfPacketSent = FALSE;
  422. }
  423. else
  424. {
  425.     pRendInfo->m_bDurationTimeSyncSent  = TRUE;
  426. }
  427. m_pPlayer->m_pScheduler->Remove(
  428.          pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
  429.         
  430.         pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
  431. if (!pRendInfo->m_bInitialBeginToBeSent)
  432. {
  433.     pRendInfo->m_bInitialBeginToBeSent  = TRUE;
  434.     m_pPlayer->EnterToBeginList(pRendInfo);
  435. }
  436. if (m_pSource->IsLive())
  437. {
  438.     pRendInfo->m_BufferingReason    = BUFFERING_LIVE_PAUSE;
  439. }
  440. else
  441. {
  442.     pRendInfo->m_BufferingReason    = BUFFERING_SEEK;
  443. }
  444.     }
  445.     m_bSeekToLastFrame = bSeekToLastFrame;
  446.     m_llLatestPacketTime = 0;
  447.     return HXR_OK;
  448. }
  449. HX_RESULT
  450. SourceInfo::BeginTrack(void)
  451. {
  452. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  453.     HX_RESULT     rc = HXR_OK;
  454.     UINT32     ulDelay = 0;
  455.     UINT32     ulPausedTime = 0;
  456.     RendererInfo*   pRendInfo = NULL;
  457.     STREAM_INFO*    pStreamInfo = NULL;
  458.     CHXAudioPlayer* pAudioPlayer = NULL;
  459.     CHXMapLongToObj::Iterator ndxRend;
  460.     if (!m_pSource)
  461.     {
  462. rc = HXR_UNEXPECTED;
  463. goto cleanup;
  464.     }
  465.     if (m_pSource->IsPaused())
  466.     {
  467. ulPausedTime = m_pPlayer->m_ulCurrentPlayTime - m_ulPausedStartTime;
  468. ulDelay = m_pSource->GetDelay() + ulPausedTime;
  469. // update source's delay time which will call sourceinfo's
  470. // UpdateDelay()
  471. m_pSource->UpdateDelay(ulDelay);
  472. // resume
  473. m_pSource->ResumeAudioStreams();
  474. rc = Begin();
  475.     }
  476.     // track is stopped ahead of its duration
  477.     else if (m_bStopped)
  478.     {
  479. m_bStopped = FALSE;
  480. m_bSeekPending = TRUE;
  481. m_ulSeekTime = m_pPlayer->m_ulCurrentPlayTime;
  482. m_pSource->ReSetup();
  483.     }
  484.     // either track has not been played yet
  485.     // or track is still playing
  486.     else
  487.     {
  488.      rc = HXR_FAILED;
  489. goto cleanup;
  490.     }
  491.    
  492. cleanup:
  493.     
  494.     return rc;
  495. #else
  496.     return HXR_NOTIMPL;
  497. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  498. }
  499. HX_RESULT
  500. SourceInfo::PauseTrack(void)
  501. {
  502. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  503.     HX_RESULT rc = HXR_OK;
  504.     // stop the source
  505.     if (m_pSource)
  506.     {
  507. m_pSource->PauseAudioStreams();
  508.     }
  509.     m_ulPausedStartTime = m_pPlayer->m_ulCurrentPlayTime;
  510.     rc = Pause();
  511.     return rc;
  512. #else
  513.     return HXR_NOTIMPL;
  514. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  515. }
  516. HX_RESULT
  517. SourceInfo::SeekTrack(UINT32 ulSeekTime)
  518. {
  519.     // low priority since it is rarely used by the SMIL
  520.     return HXR_NOTIMPL;
  521. }
  522. HX_RESULT
  523. SourceInfo::StopTrack(void)
  524. {
  525. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  526.     HX_RESULT rc = HXR_OK;
  527.     m_bStopped = TRUE;
  528.     // stop the source
  529.     if (m_pSource)
  530.     {
  531. m_pSource->RemoveAudioStreams();
  532.     }
  533.     Reset();
  534.     m_bDone = TRUE;
  535.     m_pPlayer->m_uNumSourcesActive--;
  536.     return rc;
  537. #else
  538.     return HXR_NOTIMPL;
  539. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  540. }
  541. HX_RESULT
  542. SourceInfo::SetSoundLevel(UINT16 uSoundLevel, BOOL bReflushAudioDevice)
  543. {
  544.     m_uSoundLevel = uSoundLevel;
  545.     m_pSource->SetSoundLevel(uSoundLevel, bReflushAudioDevice);
  546.     return HXR_OK;
  547. }
  548. void
  549. SourceInfo::Reset()
  550. {
  551.     /* m_pSource should never be NULL */
  552.     HX_ASSERT(m_pSource);
  553.     if (!m_pSource)
  554.     {
  555. return;
  556.     }
  557. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  558.     if(m_bIsPersistentSource)
  559.     {
  560. m_bDone = FALSE;
  561. m_bAllPacketsReceived = FALSE;
  562. CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  563. for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  564. {
  565.     RendererInfo* pRendInfo     = (RendererInfo*)(*ndxRend);
  566.     IHXRenderer* pRend         = (IHXRenderer*)pRendInfo->m_pRenderer;
  567.     STREAM_INFO*  pStreamInfo   = pRendInfo->m_pStreamInfo;
  568.     pStreamInfo->m_bSrcInfoStreamDone  = FALSE;
  569.     /* Reset the latest packet time */
  570.     pRendInfo->m_ulLatestEventTime     = 0;
  571.     m_pPlayer->m_pScheduler->Remove(
  572.              pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
  573.         
  574.             pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
  575.     pRendInfo->m_bIsFirstCallback     = TRUE;
  576.     pRendInfo->m_ulLastSyncTime         = 0;
  577.     pRendInfo->m_ulNumberOfPacketsQueued= 0;
  578.     pRendInfo->m_ulNextDueSyncTime      = 0;
  579.     if (!pRendInfo->m_bInitialBeginToBeSent && pRendInfo->m_pRenderer)
  580.     {
  581. pRendInfo->m_bInitialBeginToBeSent  = TRUE;
  582. m_pPlayer->EnterToBeginList(pRendInfo);
  583.     }
  584. }
  585.     }
  586.     else
  587. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  588.     {
  589. DoCleanup();
  590. RenderersCleanup();
  591.     }
  592.     return;
  593. }
  594. void
  595. SourceInfo::DoCleanup(EndCode endCode)
  596. {
  597.     if (m_pProcessCallback && m_pPlayer->m_pScheduler)
  598.     {
  599. m_pPlayer->m_pScheduler->Remove(m_pProcessCallback->GetPendingCallback());
  600.         m_pProcessCallback->CallbackCanceled();
  601.     }
  602.     if (m_bIsPersistentSource)
  603.     {
  604. return;
  605.     }
  606.     m_bLocked = TRUE;
  607.     m_pMutex->Lock();
  608.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  609.     for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  610.     {
  611. RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  612. /* Tell each renderer that we are done with the stream */
  613. if(pRendInfo)
  614. {
  615.             if (pRendInfo->m_pStream &&
  616.                 pRendInfo->m_pStreamInfo && pRendInfo->m_pStreamInfo->m_pHeader)
  617.             {
  618.                 IHXBuffer* pMimeTypeBuffer = NULL;
  619.         pRendInfo->m_pStreamInfo->m_pHeader->GetPropertyCString("MimeType", pMimeTypeBuffer);
  620.         if (pMimeTypeBuffer && pMimeTypeBuffer->GetBuffer() &&
  621.                     ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objectsstream") == 0 ||
  622.                     ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/x-rn-objects") == 0 ||
  623.     ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objects") == 0)
  624.         {
  625.             m_pPlayer->m_pEngine->m_lROBActive--;
  626.                     HX_ASSERT(m_pPlayer->m_pEngine->m_lROBActive >=0 );
  627.         }
  628.                 HX_RELEASE(pMimeTypeBuffer);
  629.             }
  630.     if(pRendInfo->m_pRenderer)
  631. pRendInfo->m_pRenderer->EndStream();
  632.     if (pRendInfo->m_bInitialBeginToBeSent)
  633.     {
  634. m_pPlayer->RemoveFromPendingList(pRendInfo);
  635.     }
  636.     if (pRendInfo->m_pTimeSyncCallback)
  637.     {
  638. //{FILE* f1 = ::fopen("c:\temp\ts.txt", "a+"); ::fprintf(f1, "%p RELEASING TimeSyncCallback: Pending: %d Handle: %lun", pRendInfo->m_pTimeSyncCallback, (int)pRendInfo->m_bIsCallbackPending, (UINT32) pRendInfo->m_PendingHandle);::fclose(f1);}
  639.         m_pPlayer->m_pScheduler->Remove(
  640.                  pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
  641.         
  642.                 pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
  643.                 HX_RELEASE(pRendInfo->m_pTimeSyncCallback);
  644.     }
  645.     HX_RELEASE(pRendInfo->m_pStream);
  646. }
  647.     }
  648.     // cleanup (i.e. registry)
  649.     m_pSource->DoCleanup(endCode);
  650.     UnRegister();
  651.     m_lastError = HXR_OK;
  652.     m_bAreStreamsSetup = FALSE;
  653.     m_bDone = FALSE;
  654.     m_bInitialized = FALSE;
  655.     m_bSeekPending = FALSE;
  656.     m_bSeekToLastFrame = FALSE;
  657.     m_pMutex->Unlock();
  658.     m_bLocked = FALSE;
  659. }
  660. void
  661. SourceInfo::Stop(EndCode endCode)
  662. {
  663.     /* We have already been here once */
  664.     if (m_pSource == NULL)
  665.     {
  666. return;
  667.     }
  668.     DoCleanup(endCode);
  669.     if (m_bIsPersistentSource)
  670.     {
  671. return;
  672.     }
  673.     m_bLocked = TRUE;
  674.     m_pMutex->Lock();
  675.     m_pSource->Stop();
  676. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  677.     if (m_bTrackStoppedToBeSent)
  678.     {
  679. m_pPlayer->m_pGroupManager->TrackStopped(m_uGroupID, m_uTrackID);  
  680. m_bTrackStoppedToBeSent = FALSE;
  681. if (m_pPeerSourceInfo)
  682. {
  683.     m_pPeerSourceInfo->m_bTrackStoppedToBeSent = FALSE;
  684. }
  685.     }
  686. #endif /* HELIX_FEATURE_BASICGROUPMGR */
  687.     m_pMutex->Unlock();
  688.     m_bLocked = FALSE;
  689. }
  690. void
  691. SourceInfo::Remove()
  692. {
  693.     // stop the source
  694.     if (m_pSource)
  695.     {
  696. m_pSource->RemoveAudioStreams();
  697.     }
  698.     m_bDone = TRUE;
  699.     Stop();
  700.     CloseRenderers();
  701. }
  702. /*
  703.  * -- LIVE SYNC SUPPORT --
  704.  *
  705.  * SharedWallClock class is used for live sync support.
  706.  * There is one of these objects per shared wall clock.
  707.  *
  708.  * This object will also be associated with an HXPlayer
  709.  * since we won't ever share wall clocks between two players.
  710.  * This is an intentional design choice, since it doesn't
  711.  * reall make sense to do any sync-ing across multiple players.
  712.  * 
  713.  * This object will keep a list of source's that are sharing
  714.  * it. This is mainly needed so that the wall clock can
  715.  * reset the start time for all the sources in the event that
  716.  * it gets a new start time that is earlier than it had
  717.  * previously thought. Basically, the start time of the wall
  718.  * clock is what does the syncing.      
  719.  */
  720. SharedWallClock::SharedWallClock
  721. (
  722.     const char* pName, 
  723.     UINT32 ulStartTime,
  724.     HXPlayer* pPlayer
  725. )
  726.     : m_ulStartTime(ulStartTime)
  727.     , m_strName(pName)
  728.     , m_pPlayer(pPlayer)
  729. {
  730.     HX_ASSERT(m_pPlayer);
  731.     (*m_pPlayer->m_pSharedWallClocks)[pName] = this;
  732. };
  733. /*
  734.  * -- LIVE SYNC SUPPORT --
  735.  *
  736.  * Obviously this is the method that handles resyncing the
  737.  * start times for all the sources that share the wall clock.
  738.  *
  739.  * This method also returns the start time. The intended useage
  740.  * is for the caller to pass the start time that it expects, and
  741.  * then respect the start time that is returned. In the event that
  742.  * the input start time is less than the previously known start
  743.  * time, then all sources are reset.
  744.  */
  745. UINT32
  746. SharedWallClock::ResetStartTime(UINT32 ulStartTime)
  747. {
  748.     if (ulStartTime < m_ulStartTime)
  749.     {
  750. m_ulStartTime = ulStartTime;
  751. CHXSimpleList::Iterator indx = m_UserList.Begin();
  752. for (; indx != m_UserList.End(); ++indx)
  753. {
  754.     SourceInfo* pSourceInfo = (SourceInfo*)(*indx);
  755.     pSourceInfo->ResetStartTime(ulStartTime);
  756. }
  757.     }
  758.     return m_ulStartTime;
  759. };
  760. /*
  761.  * -- LIVE SYNC SUPPORT --
  762.  *
  763.  * Nothing tricky here, we just track the incoming user on our
  764.  * list of known users.
  765.  */
  766. void
  767. SharedWallClock::AddUser(SourceInfo* pSourceInfo)
  768. {
  769.     m_UserList.AddTail(pSourceInfo);
  770. };
  771. /*
  772.  * -- LIVE SYNC SUPPORT --
  773.  *
  774.  * This method removes users from the shared clock's user list
  775.  * and also cleans up the shared clock when the last user is
  776.  * removed. So, any caller of this method should take note to
  777.  * NOT use the shared clock after calling this method.
  778.  */
  779. void
  780. SharedWallClock::RemoveUser(SourceInfo* pSourceInfo)
  781. {
  782.     LISTPOSITION pos = m_UserList.Find(pSourceInfo);
  783.     HX_ASSERT(pos);
  784.     m_UserList.RemoveAt(pos);
  785.     
  786.     if (m_UserList.IsEmpty())
  787.     {
  788. m_pPlayer->m_pSharedWallClocks->RemoveKey(m_strName);
  789. delete this;
  790.     }
  791. };
  792. /*
  793.  * -- LIVE SYNC SUPPORT --
  794.  *
  795.  * If the start time is changed for a source then all the
  796.  * renderer's need to have their start time's reset. This
  797.  * method just loops through the renderer info to do the work.
  798.  */
  799. void
  800. SourceInfo::ResetStartTime(UINT32 ulStartTime)
  801. {
  802.     if (ulStartTime < m_ulStreamStartTime)
  803.     {
  804. m_ulStreamStartTime = ulStartTime;
  805. CHXMapLongToObj::Iterator indx = m_pRendererMap->Begin();
  806. for (; indx != m_pRendererMap->End(); ++indx)
  807. {
  808.     RendererInfo* pRendererInfo = (RendererInfo*)(*indx);
  809.     pRendererInfo->m_ulStreamStartTime = ulStartTime;
  810. }
  811.     }
  812. };
  813. /*
  814.  * -- LIVE SYNC SUPPORT --
  815.  *
  816.  * This is the real work horse for live sync support. This
  817.  * method actually determines if the URL for the source is
  818.  * targeted at a shared wall clock by looking for the wallclock
  819.  * option in the URL.
  820.  *
  821.  * If the wallclock name is found then we try to find the wall
  822.  * clock object for this name and player. If we don't find it
  823.  * then we create a new clock. If we do find it then we want
  824.  * to determine if the start time should be reset to the lower
  825.  * value. We also return the start time to be stored in the
  826.  * renderers.
  827.  */
  828. UINT32
  829. SourceInfo::CalculateLiveStartTime(IHXPacket* pFirstPacket)
  830. {
  831.     UINT32 ulStreamStartTime = pFirstPacket->GetTime();;
  832.     /*
  833.      * Find out if this live feed has a "wallclock" property.
  834.      */
  835.     CHXURL* pURL = m_pSource->GetCHXURL();
  836.     IHXValues*  pValues = pURL->GetOptions();
  837.     IHXBuffer* pWallClockName = NULL;
  838.     pValues->GetPropertyBuffer("wallclock", pWallClockName);
  839.     if (pWallClockName)
  840.     {
  841. m_strWallClockName = (const char*)pWallClockName->GetBuffer();
  842. /* We shouldn't already have a wall clock! */
  843. HX_ASSERT(m_pWallClock == NULL);
  844. /*
  845.  * Lookup a wall clock with this name, if it's not found then
  846.  * we are the first one, and we should create a shared wallclock
  847.  * object, add it to the list, and do the standard setup.
  848.  */
  849. void* pLookupResult = NULL;
  850. if (!m_pPlayer->FindSharedWallClocks(m_strWallClockName,pLookupResult))
  851. {
  852.     m_pWallClock = new SharedWallClock(m_strWallClockName,
  853. ulStreamStartTime,
  854. m_pPlayer);
  855. }
  856. else
  857. {
  858.     m_pWallClock = (SharedWallClock*)pLookupResult;
  859.     ulStreamStartTime = m_pWallClock->ResetStartTime(ulStreamStartTime);
  860. }
  861. m_pWallClock->AddUser(this);
  862.     }
  863.     HX_RELEASE(pValues);
  864.     HX_RELEASE(pWallClockName);
  865.     return ulStreamStartTime;
  866. }
  867. /*
  868.  * -- LIVE SYNC SUPPORT --
  869.  *
  870.  * Basic clean up support for wall clock object. Notice that after
  871.  * calling RemoveUser, you can use the wall clock object since it
  872.  * may get deleted... so we always reset our wall clock object
  873.  * pointer to NULL.
  874.  */
  875. void
  876. SourceInfo::DoneWithWallClock()
  877. {
  878.     if (m_pWallClock)
  879.     {
  880. m_pWallClock->RemoveUser(this);
  881. m_pWallClock = NULL;
  882.     }
  883. }
  884. HX_RESULT
  885. SourceInfo::ProcessIdle(BOOL     bIsFirst,
  886.         ULONG32&    ulNumStreamsToBeFilled,
  887.         BOOL&       bIsBuffering,
  888.         UINT16&     uLowestBuffering,
  889.         BOOL     bPersistent)
  890. {
  891.     HX_RESULT theErr     = HXR_OK;
  892.     CHXEvent*          pEvent              = NULL;
  893.     HXSource*          pSource             = NULL;
  894.     IHXPendingStatus*  pStatus             = NULL;
  895.     RendererInfo*       pRendInfo           = NULL;
  896.     IHXValues*         pHeader             = NULL;
  897.     HXStream*          pStream             = NULL;
  898.     IHXRenderer*       pRenderer           = NULL;
  899.     STREAM_INFO*        pStreamInfo         = NULL;
  900.     IHXPacket*         pPacket             = NULL;
  901.     UINT16              unStatusCode        = 0;
  902.     UINT16              unPercentDone       = 0;
  903.     UINT32 ulPacketTime     = 0;
  904.     INT64 llActualPacketTime  = 0;
  905.     INT64 llLastExpectedPacketTime = 0;
  906.     IHXBuffer*         pStatusDesc         = NULL;
  907.     BOOL bAtInterrupt     = FALSE;
  908.     bAtInterrupt = m_pPlayer->m_pEngine->AtInterruptTime();
  909.     if (m_bStopped)
  910.     {
  911. return HXR_OK;
  912.     }
  913.     /* Check if a source has not been initialized. This will happen
  914.      * ONLY when we start a new track in the mid of a presentation
  915.      */
  916.     if (!m_bInitialized)
  917.     {
  918. /* Do not initialize source at interrupt time */
  919. if (bAtInterrupt)
  920. {
  921.     ScheduleProcessCallback();
  922.     return HXR_OK;
  923. }
  924. theErr = InitializeAndSetupRendererSites();
  925. if (theErr || !m_bInitialized)
  926. {
  927.     return theErr;
  928. }
  929.     }
  930.     if (m_bSeekPending)
  931.     {
  932. m_bSeekPending = FALSE;
  933. Pause();
  934. Seek(m_ulSeekTime);
  935. m_pSource->DoSeek(m_ulSeekTime);
  936. Begin();
  937.     }
  938.     pSource = m_pSource;
  939.     pStatus = m_pStatus;
  940.     // don't start getting events till the player setup has been
  941.     // done   
  942.     if (!m_pPlayer->m_bInitialized  || 
  943. m_pPlayer->m_bSetupToBeDone || 
  944. m_pPlayer->m_bPostSetupToBeDone)
  945.     {
  946. return HXR_OK;
  947.     }
  948.     
  949.     UINT16  uIndex = 0;
  950.     BOOL    bHandled = TRUE;
  951.     llLastExpectedPacketTime = m_pSource->GetLastExpectedPacketTime();
  952.     LISTPOSITION posRend = m_pCurrentScheduleList->GetHeadPosition();
  953.     for (; uIndex < m_pCurrentScheduleList->GetCount(); uIndex++)
  954.     {
  955. BOOL bSentMe = TRUE;
  956. BOOL bEndMe = FALSE;
  957. llActualPacketTime = 0;
  958. theErr = HXR_OK;
  959. if (uIndex > 0)
  960. {
  961.     if (bHandled)
  962.     {
  963. posRend = m_pCurrentScheduleList->RemoveAt(posRend);
  964. LISTPOSITION listRet = m_pCurrentScheduleList->AddTail(pRendInfo);
  965.                 // This check is critical for catching oom errors. XXXJHHB
  966.                 if( listRet == NULL )
  967.                 {
  968.                     return HXR_OUTOFMEMORY;
  969.                 }
  970.     }
  971.     else
  972.     {
  973. m_pCurrentScheduleList->GetNext(posRend);
  974.     }
  975. }
  976. bHandled = TRUE;
  977. pRendInfo       = (RendererInfo*) 
  978. m_pCurrentScheduleList->GetAt(posRend);
  979. pStreamInfo     = pRendInfo->m_pStreamInfo;
  980. if (pStreamInfo->m_bSrcInfoStreamDone)
  981. {
  982.     // SPECIAL CASE:
  983.     // the player received all the packets(m_bSrcStreamDone is TRUE) and 
  984.     // EndOfPacket() hasn't been sent to the renderer yet, 
  985.     // BUT the renderer still calls ReportRebufferStatus()
  986.     if (!IsRebufferDone())
  987.     {
  988. bIsBuffering = TRUE;
  989.     }
  990.     else
  991.     {
  992. CheckIfDone();
  993.     }
  994.     continue;
  995. }
  996. if (bIsFirst)
  997. {
  998.     pStreamInfo->m_bSrcInfoStreamFillingDone = FALSE;
  999.     ulNumStreamsToBeFilled++;
  1000. }
  1001. BOOL bThisSourceBuffering = FALSE;
  1002. if (!bPersistent)
  1003. {
  1004.     // every HXSource has to implement IID_IHXPendingStatus
  1005.     HX_ASSERT(pStatus);
  1006.     HX_VERIFY(HXR_OK == pStatus->GetStatus(unStatusCode, pStatusDesc,
  1007.    unPercentDone));
  1008.     HX_RELEASE(pStatusDesc);
  1009.     if ((HX_STATUS_BUFFERING == unStatusCode && unPercentDone < 100) ||
  1010. HX_STATUS_CONTACTING == unStatusCode)
  1011.     {
  1012. bIsBuffering            = TRUE;
  1013. bThisSourceBuffering    = TRUE;
  1014. if (uLowestBuffering > unPercentDone)
  1015. {
  1016.     uLowestBuffering = unPercentDone;
  1017. }
  1018.     }
  1019. }
  1020. /* the event times are actual ts - preroll.. so we do not
  1021.  * need to add preroll in calculations here...
  1022.  */   
  1023.  
  1024. UINT32 ulDeliveryTime = m_pPlayer->m_ulCurrentPlayTime + 
  1025.         m_pPlayer->m_ulLowestGranularity;
  1026. #ifdef _MACINTOSH
  1027. #define ADDITIONAL_PREDELIVERY_TIME 4000
  1028.   /* on Mac we try to be even farther ahead than the timeline in
  1029.    * packet delivery since the callbacks are not that smooth
  1030.    * and if we are really close to the wire, it results in
  1031.    * unnecccessary re-buffers. 
  1032.    */ 
  1033. ulDeliveryTime += ADDITIONAL_PREDELIVERY_TIME;
  1034. #endif
  1035. if (pSource)
  1036. {
  1037.     pSource->FillRecordControl();
  1038. }
  1039. if (bPersistent || bThisSourceBuffering ||
  1040.     (pRendInfo->m_ulLatestEventTime <= ulDeliveryTime))
  1041. {   
  1042.          theErr = pSource->GetEvent(pStreamInfo->m_uStreamNumber, pEvent);
  1043.     if (!theErr)
  1044.     {
  1045. pPacket = pEvent->GetPacket();
  1046. if (pEvent->IsPreSeekEvent())
  1047. {
  1048.      // associate the packet with its renderer..
  1049.      pEvent->m_pRendererInfo   = pRendInfo;     
  1050.      if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
  1051.      {
  1052.  theErr = m_pPlayer->SendPacket(pEvent);
  1053.  delete pEvent;
  1054.      }
  1055.      else
  1056.      {
  1057. // insert event in the common packet/event list...
  1058. theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
  1059.                         if( theErr == HXR_OUTOFMEMORY )
  1060.                         {
  1061.                             return HXR_OUTOFMEMORY;
  1062.                         }
  1063. pRendInfo->m_ulNumberOfPacketsQueued++;
  1064.      }
  1065.      continue;
  1066. }
  1067. if (!pPacket->IsLost())
  1068. {
  1069.     ulPacketTime = pPacket->GetTime();
  1070.     llActualPacketTime = 
  1071. pRendInfo->m_pStreamInfo->BufferingState().CreateINT64Timestamp(ulPacketTime);
  1072.     if (m_llLatestPacketTime < llActualPacketTime)
  1073.     {
  1074. m_llLatestPacketTime = llActualPacketTime;
  1075.     }
  1076.     pRendInfo->m_ulLatestEventTime  = pEvent->GetTimeStartPos();
  1077.     
  1078.     if (pSource->IsLive() && pRendInfo->m_bIsFirstPacket)
  1079.     {
  1080. pRendInfo->m_bIsFirstPacket     = FALSE;
  1081. /*
  1082.  * -- LIVE SYNC SUPPORT --
  1083.  *
  1084.  * We used to just set the stream start time to the 
  1085.  * timestamp of this first packet. Now we use this
  1086.  * helper function to implement support for sharing
  1087.  * start times for sources off of the same wall clock.
  1088.  * See other LIVE SYNC SUPPORT comments for more 
  1089.  * details.
  1090.  */
  1091. UINT32 ulLiveStart = CalculateLiveStartTime(pPacket);
  1092. pRendInfo->m_ulStreamStartTime = ulLiveStart;
  1093. m_ulStreamStartTime = ulLiveStart;
  1094. UINT32  ulLowestTime = 0;
  1095. BOOL    bAtLeastOneLowestTime = FALSE;
  1096. UINT16  uNumLowestKnown = 0;
  1097. CHXMapLongToObj::Iterator tmpndxRend = m_pRendererMap->Begin();
  1098. for (;!theErr && tmpndxRend != m_pRendererMap->End();
  1099. ++tmpndxRend)
  1100. {
  1101.     RendererInfo* pTmpRendInfo  = (RendererInfo*)(*tmpndxRend);
  1102.     /* Have we received the lowest packet?*/
  1103.     if (!pTmpRendInfo->m_bIsFirstPacket)
  1104.     {
  1105. uNumLowestKnown++;
  1106. if (!bAtLeastOneLowestTime)
  1107. {
  1108.     bAtLeastOneLowestTime = TRUE;
  1109.     ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
  1110.     SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
  1111. }
  1112. else
  1113. {
  1114.     if (ulLowestTime > pTmpRendInfo->m_ulStreamStartTime)
  1115.     {
  1116. ulLowestTime = pTmpRendInfo->m_ulStreamStartTime;
  1117.     }
  1118. }
  1119.     }
  1120. }
  1121. if (uNumLowestKnown > 1)
  1122. {
  1123.     tmpndxRend = m_pRendererMap->Begin();
  1124.     for (;!theErr && tmpndxRend != m_pRendererMap->End();
  1125.     ++tmpndxRend)
  1126.     {
  1127. RendererInfo* pTmpRendInfo      = (RendererInfo*)(*tmpndxRend);
  1128. /* Have we received the lowest packet?*/
  1129. if (!pTmpRendInfo->m_bIsFirstPacket)
  1130. {
  1131.     pTmpRendInfo->m_ulStreamStartTime = ulLowestTime;
  1132.     SetLiveSyncStartTime(pSource, pTmpRendInfo, ulLowestTime);
  1133. }
  1134.     }
  1135. }
  1136.     }
  1137.     if ((!pSource->IsLive() || pSource->isRestrictedLiveStream()) &&
  1138. llActualPacketTime > llLastExpectedPacketTime)
  1139.     {
  1140. // XXX HP
  1141. // work around since the rule flag of all RTSP packets are set to
  1142. // HX_ASM_SWITCH_ON only and this could cause the stream doesn't end 
  1143. // properly if its endtime was changed after the first resume has been 
  1144. // sent
  1145. // THIS WILL BE FIXED IN THE NEXT SERVER RELEASE("dial-tone")  
  1146. if (pSource->m_bRTSPRuleFlagWorkAround)
  1147. {
  1148.     bSentMe = FALSE;
  1149.     bEndMe = TRUE;
  1150. }
  1151. else 
  1152. {
  1153.     pRendInfo->m_pStream->PostEndTimePacket(pPacket, bSentMe, bEndMe);
  1154. }
  1155.     }
  1156. }     
  1157. if (bSentMe)
  1158. {     
  1159.     // clear up the post events which were not sent
  1160.     if (pStreamInfo->m_pPostEndTimeEventList)
  1161.     {
  1162. while (pStreamInfo->m_pPostEndTimeEventList->GetNumEvents())
  1163. {
  1164.     CHXEvent* pPostEndTimeEvent = pStreamInfo->m_pPostEndTimeEventList->RemoveHead();
  1165.     // associate the packet with its renderer..
  1166.     pPostEndTimeEvent->m_pRendererInfo   = pRendInfo;
  1167.     // insert event in the common packet/event list...
  1168.     theErr = m_pPlayer->m_EventList.InsertEvent(pPostEndTimeEvent);
  1169.                             if( theErr == HXR_OUTOFMEMORY )
  1170.                             {
  1171.                                 return HXR_OUTOFMEMORY;
  1172.     }
  1173.     pRendInfo->m_ulNumberOfPacketsQueued++;
  1174. }
  1175.     }
  1176.     // associate the packet with its renderer..
  1177.     pEvent->m_pRendererInfo   = pRendInfo;
  1178.     // insert event in the common packet/event list...
  1179.     theErr = m_pPlayer->m_EventList.InsertEvent(pEvent);
  1180.     if( theErr == HXR_OUTOFMEMORY )
  1181.                     {
  1182.                         return HXR_OUTOFMEMORY;
  1183.     }
  1184.     pRendInfo->m_ulNumberOfPacketsQueued++;
  1185. }
  1186. else
  1187. {
  1188.     if (!pStreamInfo->m_pPostEndTimeEventList)
  1189.     {
  1190. pStreamInfo->m_pPostEndTimeEventList = new CHXEventList();
  1191.     }
  1192.     if (pStreamInfo->m_pPostEndTimeEventList)
  1193.     {
  1194. //{FILE* f1 = ::fopen("c:\temp\out.txt", "a+"); ::fprintf(f1, "bSentMe is FALSE PacketTime: %lu PacketRule: %un", pEvent->GetPacket()->GetTime(), pEvent->GetPacket()->GetASMRuleNumber());::fclose(f1);}
  1195. theErr = pStreamInfo->m_pPostEndTimeEventList->InsertEvent(pEvent);
  1196. if( theErr == HXR_OUTOFMEMORY )
  1197. {
  1198.     return theErr;
  1199. }
  1200.     }
  1201. }
  1202.     }
  1203.     else
  1204.     {
  1205. bHandled = FALSE;
  1206.     }
  1207.     if (theErr && !bPersistent)
  1208.     {
  1209. if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
  1210.     ulNumStreamsToBeFilled > 0)
  1211. {
  1212.     pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
  1213.     ulNumStreamsToBeFilled--;
  1214. }
  1215.     }
  1216. }
  1217. else
  1218. {
  1219.     if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
  1220. ulNumStreamsToBeFilled > 0)
  1221.     {
  1222. pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
  1223. ulNumStreamsToBeFilled--;
  1224.     }
  1225. }
  1226. if (theErr == HXR_BUFFERING)
  1227. {
  1228.     if (bPersistent)
  1229.     {
  1230. bIsBuffering    = TRUE;
  1231.     }
  1232. }
  1233. else if (theErr == HXR_AT_END)
  1234. {
  1235.     if (!pStreamInfo->m_bSrcInfoStreamDone)
  1236.     {
  1237. if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
  1238. {
  1239.     pStreamInfo->m_bSrcInfoStreamDone = TRUE;
  1240.     pStreamInfo->ResetPostEndTimeEventList();
  1241.     if (pRendInfo->m_ulNumberOfPacketsQueued == 0 &&
  1242. pRendInfo->m_pRenderer)
  1243.     {
  1244. m_pPlayer->SendPostSeekIfNecessary(pRendInfo);
  1245. pRendInfo->m_pRenderer->OnEndofPackets();
  1246. pRendInfo->m_bOnEndOfPacketSent = TRUE;
  1247.     }
  1248.     CheckIfDone();
  1249. }
  1250. else
  1251. {
  1252.     ScheduleProcessCallback();
  1253.     continue;
  1254. }
  1255.     }
  1256. }
  1257. else if (theErr == HXR_NO_DATA)
  1258. {
  1259.     /* mask this error */
  1260.     theErr  = HXR_OK;
  1261. }
  1262. if (!llActualPacketTime)
  1263. {
  1264.     STREAM_INFO* pStrInfo = pRendInfo->m_pStreamInfo;
  1265.     UINT32 ulPktTime = 
  1266. pStrInfo->BufferingState().LastPacketTimestamp();
  1267.     llActualPacketTime = 
  1268. pStrInfo->BufferingState().CreateINT64Timestamp(ulPktTime);
  1269.     
  1270.     /* if this is a stream where we do not have to wait to receive 
  1271.      * a packet >= stream's last expected packet time, 
  1272.      * make the highest timestamp to be the HIGHEST timestamp
  1273.      * across ALL streams for this source.
  1274.      *
  1275.      * This is to fix end tag support on sources with sparse streams
  1276.      * e.g. audio/video with an event stream where we may not really 
  1277.      * have a packet till way down in the future.  
  1278.      */ 
  1279.     if (pRendInfo->m_pStreamInfo->m_bCanBeStoppedAnyTime &&
  1280. !pStreamInfo->m_bSrcInfoStreamDone &&
  1281. m_llLatestPacketTime > llLastExpectedPacketTime)
  1282.     {
  1283. /* check if ALL other streams have ended */
  1284. if (AllOtherStreamsHaveEnded(pStreamInfo))
  1285. {
  1286.                     /*
  1287.                      * The logic above was designed to handle endTime's
  1288.                      * on a/v streams, so that once we received a/v packets
  1289.                      * past the end time (even though more packets are 
  1290.                      * still coming in), we can go ahead and end the
  1291.                      * event stream. However, this was causing a bug
  1292.                      * where syncmm event streams were getting terminated
  1293.                      * even though there was a packet waiting for it
  1294.                      * at the transport. This additional test imposes
  1295.                      * that we don't terminate the stream unless we
  1296.                      * have no packets waiting at the transport AND
  1297.                      * the stream has said it's done.
  1298.                      */
  1299.                     if (pStreamInfo->BufferingState().DoneAtTransport())
  1300.                     {
  1301.              bEndMe = TRUE;
  1302.         llActualPacketTime  = m_llLatestPacketTime;
  1303.                     }
  1304. }
  1305.     }
  1306. }
  1307. if (!bPersistent && 
  1308.     (!pSource->IsLive() || pSource->isRestrictedLiveStream()) && 
  1309.     !pStreamInfo->m_bSrcInfoStreamDone &&
  1310.     llActualPacketTime > llLastExpectedPacketTime &&
  1311.     bEndMe)
  1312. {
  1313.     if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
  1314.     {
  1315. pStreamInfo->m_bSrcInfoStreamDone = TRUE;
  1316. pStreamInfo->ResetPostEndTimeEventList();
  1317. if (!pStreamInfo->m_bSrcInfoStreamFillingDone &&
  1318.     ulNumStreamsToBeFilled > 0)
  1319. {
  1320.     pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
  1321.     ulNumStreamsToBeFilled--;
  1322. }
  1323. if (pRendInfo->m_ulNumberOfPacketsQueued == 0 &&
  1324.     pRendInfo->m_pRenderer)
  1325. {
  1326.     m_pPlayer->SendPostSeekIfNecessary(pRendInfo);
  1327.     pRendInfo->m_pRenderer->OnEndofPackets();
  1328.     pRendInfo->m_bOnEndOfPacketSent = TRUE;
  1329. }
  1330. if (!pSource->isRestrictedLiveStream())
  1331. {
  1332.     CheckIfDone();
  1333. }
  1334.     }
  1335.     else
  1336.     {
  1337. ScheduleProcessCallback();
  1338. continue;
  1339.     }
  1340. }
  1341.     }
  1342.     if (!bPersistent && 
  1343. m_bInitialized &&
  1344. m_ulSourceDuration < m_pPlayer->m_ulCurrentPlayTime && 
  1345. m_pSource && 
  1346. !m_pSource->IsLive() &&
  1347. m_pSource->IsActive())
  1348.     {
  1349. /* Remove bandwidth usage for this source */
  1350. m_pSource->AdjustClipBandwidthStats(FALSE);
  1351.     }
  1352.     else if (m_bInitialized &&
  1353.     m_pSource &&
  1354.     m_pPlayer->m_ulCurrentPlayTime > m_pSource->GetDelay() &&
  1355.     m_pPlayer->m_ulCurrentPlayTime <= m_ulSourceDuration && 
  1356.     !m_pSource->IsActive())
  1357.     {
  1358. /* Add bandwidth usage for this source */
  1359. m_pSource->AdjustClipBandwidthStats(TRUE);
  1360.     }
  1361.     return HXR_OK;
  1362. }
  1363. HX_RESULT
  1364. SourceInfo::Register()
  1365. {
  1366.     HX_RESULT theErr = HXR_OK;
  1367.     if (!m_bIsRegisterSourceDone)
  1368.     {
  1369. m_bIsRegisterSourceDone = TRUE;
  1370. if (m_pSource->m_bSureStreamClip)
  1371. {
  1372.     m_pPlayer->SureStreamSourceRegistered(this);
  1373. }
  1374. m_pSource->CanBeFastStarted();
  1375. #if defined(HELIX_FEATURE_ASM)
  1376. /* Register Source with ASM Bandwidth Manager */
  1377. IHXBandwidthManager* pMgr = 0;
  1378. HX_VERIFY(HXR_OK == m_pPlayer->QueryInterface(
  1379.     IID_IHXBandwidthManager, (void **)&pMgr));
  1380. theErr = pMgr->RegisterSource(m_pSource, (IUnknown*) (IHXPlayer*) m_pPlayer);
  1381. pMgr->Release();
  1382. #endif /* HELIX_FEATURE_ASM */
  1383.     }
  1384.     return theErr;
  1385. }
  1386. HX_RESULT
  1387. SourceInfo::UnRegister()
  1388. {
  1389.     HX_RESULT theErr = HXR_OK;
  1390.     if (m_bIsRegisterSourceDone)
  1391.     {
  1392. m_bIsRegisterSourceDone = FALSE;
  1393. if (m_pSource->m_bSureStreamClip)
  1394. {
  1395.     m_pPlayer->SureStreamSourceUnRegistered(this);
  1396. }
  1397. #if defined(HELIX_FEATURE_ASM)
  1398. /* Register Source with ASM Bandwidth Manager */
  1399. IHXBandwidthManager* pMgr = 0;
  1400. HX_VERIFY(HXR_OK == m_pPlayer->QueryInterface(
  1401.     IID_IHXBandwidthManager, (void **)&pMgr));
  1402. HX_ASSERT(pMgr) ;
  1403. if (pMgr)
  1404. {
  1405. theErr = pMgr->UnRegisterSource(m_pSource);
  1406. pMgr->Release();
  1407. }
  1408.         CheckIfDone();
  1409. #endif /* HELIX_FEATURE_ASM */
  1410.     }
  1411.     return theErr;
  1412. }
  1413. void
  1414. SourceInfo::ChangeAccelerationStatus(BOOL bMayBeAccelerated,
  1415.      BOOL bUseAccelerationFactor,
  1416.      UINT32 ulAccelerationFactor)
  1417. {
  1418.     IHXBandwidthManager* pMgr = 0;
  1419.     HX_VERIFY(HXR_OK == m_pPlayer->QueryInterface(
  1420. IID_IHXBandwidthManager, (void **)&pMgr));
  1421.     if (pMgr)
  1422.     {
  1423. pMgr->ChangeAccelerationStatus(m_pSource, bMayBeAccelerated,
  1424.        bUseAccelerationFactor, ulAccelerationFactor);
  1425. pMgr->Release();
  1426.     }
  1427. }
  1428. void SourceInfo::CheckIfDone()
  1429. {
  1430.     BOOL bIsDone = TRUE;
  1431.     CHXMapLongToObj::Iterator   ndxRend;
  1432.     RendererInfo*   pRendInfo   = NULL;
  1433.     STREAM_INFO*    pStreamInfo = NULL;
  1434.     // keep the source active throughout the duration
  1435.     // of source
  1436.     if (m_bDone &&
  1437. m_bActive && 
  1438. m_pPlayer->m_uNumSourcesActive > 0 &&
  1439. !KeepSourceActive())
  1440.     {   
  1441. m_bActive = FALSE;
  1442. m_pPlayer->m_uNumSourcesActive--;
  1443.     }
  1444.     if (!m_bDone)
  1445.     {
  1446. ndxRend = m_pRendererMap->Begin();
  1447. for (;ndxRend != m_pRendererMap->End(); ++ndxRend)
  1448. {
  1449.     pRendInfo       = (RendererInfo*)(*ndxRend);
  1450.     pStreamInfo     = pRendInfo->m_pStreamInfo;
  1451.     if (!pStreamInfo->m_bSrcInfoStreamDone)
  1452.     {
  1453. bIsDone = FALSE;
  1454. break;
  1455.     }
  1456. }
  1457. if (bIsDone || m_pSource->IsSourceDone())
  1458. {
  1459.     m_bDone = TRUE;
  1460.     if (!m_bAllPacketsReceived)
  1461.     {
  1462. m_bAllPacketsReceived = TRUE;
  1463. // If we are done receiving all the packets, release bandwidth
  1464. UnRegister();
  1465.     }
  1466.     if (!m_pSource->IsSourceDone())
  1467.     {
  1468. m_pSource->SetEndOfClip(TRUE);
  1469.     }
  1470.     if (m_pPlayer->m_uNumCurrentSourceNotDone > 0)
  1471.     {
  1472. m_pPlayer->m_uNumCurrentSourceNotDone--;
  1473.     }
  1474. }
  1475.     }
  1476. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  1477.     if (!m_bActive && 
  1478. m_bTrackStoppedToBeSent &&
  1479. !m_pPlayer->m_pEngine->AtInterruptTime())
  1480.     {
  1481. // send TrackStopped at the end of its active duration
  1482. m_bTrackStoppedToBeSent = FALSE;
  1483. m_pPlayer->m_pGroupManager->TrackStopped(m_uGroupID, m_uTrackID);  
  1484. if (m_pPeerSourceInfo)
  1485. {
  1486.     m_pPeerSourceInfo->m_bTrackStoppedToBeSent = FALSE;
  1487. }
  1488.     }
  1489. #endif /* HELIX_FEATURE_BASICGROUPMGR */
  1490. }
  1491. void
  1492. SourceInfo::SetupRendererSites(BOOL bIsPersistent)
  1493. {
  1494.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  1495.     for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  1496.     {
  1497. RendererInfo* pRendInfo   = (RendererInfo*) (*ndxRend);
  1498. IHXRenderer* pRenderer   = (IHXRenderer*) pRendInfo->m_pRenderer;
  1499. HX_DISPLAY_TYPE    ulFlags;
  1500. IHXBuffer*         pInfoBuffer = NULL;
  1501. /*
  1502.  * Find out if the renderer is a display type renderer.
  1503.  */
  1504. if (HXR_OK == pRenderer->GetDisplayType(ulFlags,pInfoBuffer))
  1505. {
  1506.     HX_RELEASE(pInfoBuffer);
  1507.     if (HX_DISPLAY_WINDOW == (HX_DISPLAY_WINDOW & ulFlags))
  1508.     {
  1509. STREAM_INFO*  pStreamInfo = pRendInfo->m_pStreamInfo;
  1510. IHXValues*   pProps      = pStreamInfo->m_pStreamProps;
  1511. /*
  1512.  * Call the helper function that handles setup of a
  1513.  * renderer site. This function will do the
  1514.  * whole process of finding out if a site exists by
  1515.  * PlayToFrom; if not, it calls the site supplier; then it
  1516.  * it actually hooks up the SiteUserSupplier with all
  1517.  * the appropriate sites, etc.
  1518.  */
  1519. m_pPlayer->SetupRendererSite(pRenderer,pProps,bIsPersistent);
  1520.     }
  1521. }
  1522.     }
  1523. }
  1524. HX_RESULT
  1525. SourceInfo::InitializeRenderers(BOOL& bSourceInitialized)
  1526. {
  1527.     HX_RESULT   theErr              = HXR_OK;
  1528.     HX_RESULT theFinalErr     = HXR_OK;
  1529.     IHXValues* pHeader             = NULL;
  1530.     HXStream*  pStream             = NULL;
  1531.     IHXRenderer*   pRenderer       = NULL;
  1532.     IHXBuffer* pMimeTypeBuffer     = NULL;
  1533.     IUnknown*   pUnkRenderer        = NULL;
  1534.     STREAM_INFO*    pStreamInfo     = NULL;
  1535.     BOOL bAddDefaultUpgrade  = FALSE;
  1536.     bSourceInitialized = FALSE;
  1537.     if (m_pPlayer->m_pEngine->AtInterruptTime()) //for Mac
  1538.     {
  1539. return HXR_OK;
  1540.     }
  1541.     if (m_pSource->GetLastError() != HXR_OK)
  1542.     {
  1543. /* Since the source has an error, mark plugin load attempt
  1544.  * to TRUE so that the player object can request upgrade
  1545.  * if it needs to
  1546.  */
  1547. m_bLoadPluginAttempted = TRUE;
  1548. return HXR_OK;
  1549.     }
  1550.     if (!m_pSource->IsInitialized())
  1551.     {
  1552. // atleast one source is not yet initialized
  1553. return HXR_OK;
  1554.     }
  1555.     bSourceInitialized = TRUE;
  1556. #if defined(HELIX_FEATURE_NESTEDMETA)
  1557.     IHXPersistentComponent* pPersistentComponent = NULL;
  1558.     if (HXR_OK == m_pPlayer->m_pPersistentComponentManager->GetPersistentComponent(m_ulPersistentComponentID,
  1559.    pPersistentComponent))
  1560.     {
  1561. // no need to AddRef() since it's maintained by PersistentManager
  1562. m_pRendererAdviseSink = ((HXPersistentComponent*)pPersistentComponent)->m_pRendererAdviseSink;
  1563. m_pRendererAdviseSink->AddRef();
  1564.     }
  1565.     HX_RELEASE(pPersistentComponent);
  1566. #endif /* HELIX_FEATURE_NESTEDMETA */
  1567.     theErr = SetupStreams();
  1568.     if (m_bIndefiniteDuration ||
  1569. m_pSource->IsLive() || 
  1570. m_pPlayer->IsLive())
  1571.     {
  1572. m_pPlayer->m_bIsLive = TRUE;
  1573. m_pPlayer->m_pAudioPlayer->SetLive(m_pPlayer->m_bIsLive);
  1574. if (m_pSource->isRestrictedLiveStream())
  1575. {
  1576.     m_pPlayer->SetPresentationTime(max(m_pPlayer->m_ulPresentationDuration, GetActiveDuration()));
  1577. }
  1578. else
  1579. {
  1580.     m_pPlayer->SetPresentationTime(0);
  1581. }
  1582.     }
  1583.     else
  1584.     {
  1585. m_pPlayer->SetPresentationTime(max(m_pPlayer->m_ulPresentationDuration, GetActiveDuration()));
  1586.     }
  1587.     // attemp to load all the plugins
  1588.     m_bLoadPluginAttempted = TRUE;
  1589.     UINT16 uNumStreams = m_pSource->GetNumStreams();
  1590.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  1591.     for (UINT16 i = 0; ndxRend != m_pRendererMap->End(); ++ndxRend, i++)
  1592.     {
  1593. RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  1594. pStreamInfo = pRendInfo->m_pStreamInfo;
  1595. pHeader         = pStreamInfo->m_pHeader;
  1596. pStream         = pRendInfo->m_pStream;
  1597. HX_ASSERT(pHeader);
  1598. HX_ASSERT(pStream);
  1599. pRenderer       = NULL;
  1600. pUnkRenderer    = NULL;
  1601. bAddDefaultUpgrade  = FALSE;
  1602. HX_RELEASE(pMimeTypeBuffer);
  1603. pHeader->GetPropertyCString("MimeType", pMimeTypeBuffer);
  1604. HX_ASSERT(pMimeTypeBuffer && pMimeTypeBuffer->GetBuffer());
  1605. if (!pMimeTypeBuffer || !pMimeTypeBuffer->GetBuffer())
  1606. {
  1607.     GOTOEXITONERROR(theErr = HXR_NOT_INITIALIZED, exit);
  1608. }
  1609. /* 
  1610.  * Check for "CanBeStoppedAnyTime" property. For streams with this 
  1611.  * property, we do not have to wait to receive a 
  1612.  * packet with timestamp >= lastPacketTime. 
  1613.  * We can instead use the highest timestamp received across
  1614.  * ALL the streams in a given source 
  1615.  */
  1616. UINT32 ulCanBeStoppedAnyTime = 0;
  1617. if (pHeader->GetPropertyULONG32("CanBeStoppedAnyTime", ulCanBeStoppedAnyTime) == HXR_OK)     
  1618. {   
  1619.     pStreamInfo->m_bCanBeStoppedAnyTime = (ulCanBeStoppedAnyTime == 1);
  1620. }
  1621. /* temporary hack till we fix rmff fileformat to correctly set this
  1622.  * property AND the servers areupdated to have this fixed fileformat.
  1623.  */
  1624. else if (::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/x-pn-realevent") == 0 ||
  1625.  ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "syncMM/x-pn-realvideo") == 0)
  1626. {
  1627.     pStreamInfo->m_bCanBeStoppedAnyTime = TRUE;
  1628. }
  1629. else if (::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objectsstream") == 0 ||
  1630.                 ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/x-rn-objects") == 0 ||
  1631.  ::strcasecmp((const char*) pMimeTypeBuffer->GetBuffer(), "application/vnd.rn-objects") == 0)
  1632. {
  1633.     m_pPlayer->m_pEngine->m_lROBActive++;
  1634. }
  1635. IHXPluginHandler3* pPlugin2Handler3 = NULL;
  1636. HX_VERIFY(HXR_OK ==
  1637.     m_pPlayer->m_pPlugin2Handler->QueryInterface(IID_IHXPluginHandler3, (void**) &pPlugin2Handler3));
  1638. if (!(HXR_OK == pPlugin2Handler3->FindGroupOfPluginsUsingStrings(PLUGIN_CLASS, PLUGIN_RENDERER_TYPE, 
  1639.     PLUGIN_RENDERER_MIME, (char*)pMimeTypeBuffer->GetBuffer(), NULL, NULL, pRendInfo->m_pRendererEnumerator) &&
  1640.     pRendInfo->m_pRendererEnumerator &&
  1641.     (HXR_OK == pRendInfo->m_pRendererEnumerator->GetNextPlugin(pUnkRenderer, NULL)) &&
  1642.     pUnkRenderer))
  1643. {
  1644. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  1645.     if(m_pPlayer->m_pUpgradeCollection)
  1646. m_pPlayer->m_pUpgradeCollection->Add(eUT_Required, pMimeTypeBuffer, 0, 0);
  1647. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  1648.     theErr = HXR_NO_RENDERER;
  1649. }
  1650. HX_RELEASE(pPlugin2Handler3);
  1651. GOTOEXITONERROR(theErr, nextrend);
  1652. tryNextRendererForSameMimeType:
  1653. HX_ASSERT(pUnkRenderer);
  1654. pUnkRenderer->QueryInterface(IID_IHXRenderer, (void**) &pRenderer);
  1655. theErr = pStream->SetRenderer(pUnkRenderer);
  1656. GOTOEXITONERROR(theErr, nextrend);
  1657. HX_RELEASE(pUnkRenderer);
  1658.         // now get the TAC info for this track/source
  1659.         UINT32 sourceID;
  1660. sourceID     = 0;
  1661.         if (HXR_OK == m_pSource->GetID(sourceID))
  1662.         {
  1663.             m_pPlayer->CheckTrackAndSourceOnTrackStarted(m_uGroupID, m_uTrackID, sourceID);
  1664.         }
  1665. if (!pStreamInfo->m_pStreamProps)
  1666. {
  1667.     // Create an IHXValues for storing stream properties related
  1668.     // to metafile initilization and layout hookup.
  1669.     pStreamInfo->m_pStreamProps = new CHXHeader();
  1670.     pStreamInfo->m_pStreamProps->AddRef();
  1671. }
  1672. IHXBuffer* pStreamPlayTo;
  1673. pStreamPlayTo = NULL;
  1674. // If the stream doesn't have a playto property, than
  1675. // check if the parent source has a playto property
  1676. if ((HXR_OK != pStreamInfo->m_pStreamProps->GetPropertyCString("playto",pStreamPlayTo)) ||
  1677.     !pStreamPlayTo)
  1678. {
  1679.     /* Set region name to playto property */
  1680.     pStreamInfo->m_pStreamProps->GetPropertyCString("region",pStreamPlayTo);
  1681.     
  1682.     /* create a unique value */
  1683.     if (!pStreamPlayTo)
  1684.     {
  1685. char szBuffer[14]; /* Flawfinder: ignore */
  1686. ULONG32 length = SafeSprintf(szBuffer,14, "%#010lx",(ULONG32)(void*)pStreamInfo); /* Flawfinder: ignore */
  1687. pStreamPlayTo = (IHXBuffer*) new CHXBuffer();
  1688. pStreamPlayTo->AddRef();
  1689. pStreamPlayTo->Set((UCHAR*)szBuffer,length+1);
  1690.     }
  1691.     pStreamInfo->m_pStreamProps->SetPropertyCString("playto",pStreamPlayTo);
  1692. }
  1693. HX_RELEASE(pStreamPlayTo);
  1694. theErr = SetupRenderer(pRendInfo, pRenderer, pStreamInfo, pStream);
  1695. nextrend:
  1696. if (theErr)
  1697. {
  1698.     if (theErr == HXR_OUTOFMEMORY)
  1699.     {
  1700. m_pPlayer->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
  1701.     }
  1702.     if (theErr == HXR_REQUEST_UPGRADE)
  1703.     {
  1704. bAddDefaultUpgrade = TRUE;
  1705.     }
  1706.     HX_RELEASE(pUnkRenderer);
  1707.     if (pRendInfo->m_pRendererEnumerator &&
  1708. HXR_OK == pRendInfo->m_pRendererEnumerator->GetNextPlugin(pUnkRenderer, NULL) &&
  1709. pUnkRenderer)
  1710.     {
  1711. theErr = HXR_OK;
  1712. HX_RELEASE(pRendInfo->m_pRenderer);
  1713. goto tryNextRendererForSameMimeType;
  1714.     }
  1715.     else
  1716.     {
  1717. if (!theFinalErr)
  1718. {
  1719.     bSourceInitialized = FALSE;
  1720.     theFinalErr = theErr;
  1721. }     
  1722. // merge any upgrade requests for this source to the player
  1723. m_pSource->MergeUpgradeRequest(bAddDefaultUpgrade, pMimeTypeBuffer ? (char*) pMimeTypeBuffer->GetBuffer() : (char*)NULL);
  1724. theErr = HXR_OK;
  1725.     }
  1726. }
  1727.     }
  1728. exit:
  1729.     if (theErr && !theFinalErr)
  1730.     {
  1731. bSourceInitialized = FALSE;
  1732. theFinalErr = theErr;
  1733.     }
  1734. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  1735.     if(!theFinalErr && 
  1736.        m_bTrackStartedToBeSent)
  1737.     {    
  1738. m_pPlayer->m_pGroupManager->TrackStarted(m_uGroupID, m_uTrackID);  
  1739. m_bTrackStartedToBeSent = FALSE;
  1740. if (m_pPeerSourceInfo)
  1741. {
  1742.     m_pPeerSourceInfo->m_bTrackStartedToBeSent = FALSE;
  1743. }
  1744.     }
  1745. #endif /* HELIX_FEATURE_BASICGROUPMGR */
  1746.     HX_RELEASE(pMimeTypeBuffer);
  1747.     HX_RELEASE(pUnkRenderer);
  1748.     if (!theFinalErr)
  1749.     {
  1750. theFinalErr = InitializeRenderersExt(bSourceInitialized);
  1751.     }
  1752.     if (!theFinalErr && bSourceInitialized)
  1753.     {
  1754. m_bInitialized = TRUE;
  1755.   
  1756. // renderers initialized...clear any pending upgrade requests for this source!
  1757. m_pSource->ClearUpgradeRequest();
  1758. if (m_bAudioDeviceReflushHint)
  1759. {
  1760.     m_pSource->SetAudioDeviceReflushHint();
  1761. }
  1762. // set the soundLevel != 100 by default
  1763. if (m_uSoundLevel != 100)
  1764. {
  1765.     m_pSource->SetSoundLevel(m_uSoundLevel, FALSE);
  1766. }
  1767. /* Enter the order of the stream numbers in which they will be 
  1768.  * scheduled for GetEvent() calls
  1769.  */
  1770. if (NULL == m_pCurrentScheduleList)
  1771. {
  1772.     m_pCurrentScheduleList = new CHXSimpleList;
  1773. }
  1774. CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  1775. for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  1776. {
  1777.     RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  1778.     m_pCurrentScheduleList->AddTail((void*) pRendInfo);
  1779. }
  1780.     }
  1781.     return theFinalErr;
  1782. }
  1783. HX_RESULT
  1784. SourceInfo::InitializeRenderersExt(BOOL& bSourceInitialized)
  1785. {
  1786.     return HXR_OK;
  1787. }
  1788. HX_RESULT
  1789. SourceInfo::SetupStreams()
  1790. {
  1791.     if (m_bAreStreamsSetup)
  1792.     {
  1793. return HXR_OK;
  1794.     }
  1795.     HX_RESULT     theErr          = HXR_OK;
  1796.     IHXValues*     pHeader         = NULL;
  1797.     HXStream*     pStream         = NULL;
  1798.     STREAM_INFO*    pStreamInfo     = NULL;
  1799.     RendererInfo*   pRendInfo       = NULL;
  1800.     HXSource*     pSource     = m_pSource;
  1801.     if (!pSource->IsInitialized())
  1802.     {
  1803. HX_ASSERT(FALSE);
  1804. return HXR_UNEXPECTED;
  1805.     }
  1806.     UINT16 uNumStreams = pSource->GetNumStreams();
  1807.     HX_ASSERT(m_pRendererMap->IsEmpty() == TRUE);
  1808.     if (m_pRendererMap->IsEmpty() && uNumStreams > 0 &&
  1809. (UINT32) uNumStreams < m_pRendererMap->GetHashTableSize())
  1810.     {
  1811. m_pRendererMap->InitHashTable((UINT32) uNumStreams);
  1812.     }
  1813.     
  1814.     for (UINT16 i=0; i < uNumStreams; i++)
  1815.     {
  1816. UINT32 ulStreamNumber = 0;
  1817. pHeader         = NULL;
  1818. pStream         = NULL;
  1819. pSource->GetStreamHeaderInfo(i, pHeader);
  1820. if (!pHeader)
  1821. {
  1822.     GOTOEXITONERROR(theErr = HXR_FAILED, exit);     
  1823. }
  1824. pStream = new HXStream;
  1825. if (!pStream)
  1826. {
  1827.     theErr = HXR_OUTOFMEMORY;
  1828.     goto exit;
  1829. }
  1830. pStream->AddRef();
  1831. theErr = pStream->Init(m_pPlayer, pSource, pHeader);
  1832. GOTOEXITONERROR(theErr, exit);
  1833. pHeader->GetPropertyULONG32("StreamNumber", ulStreamNumber);
  1834. if (HXR_OK != pSource->GetStreamInfo(ulStreamNumber, pStreamInfo) || !pStreamInfo)
  1835. {
  1836.     GOTOEXITONERROR(theErr = HXR_FAILED, exit);
  1837. }
  1838. HX_RELEASE(pHeader);
  1839. pRendInfo = NewRendererInfo();
  1840. if (!pRendInfo)
  1841. {
  1842.     theErr = HXR_OUTOFMEMORY;
  1843.     GOTOEXITONERROR(theErr, exit);
  1844. }
  1845. // get properties of the header
  1846. pRendInfo->m_pRenderer          = NULL;
  1847. pRendInfo->m_pStreamInfo        = pStreamInfo;
  1848. pRendInfo->m_ulGranularity      = 0;
  1849. pRendInfo->m_ulDuration         = pStreamInfo->m_ulDuration;
  1850. pRendInfo->m_BufferingReason    = BUFFERING_START_UP;
  1851.         
  1852.         struct timeSyncParamStruct obj = {this, pRendInfo};
  1853.         pRendInfo->m_pTimeSyncCallback  = new CTimeSyncCallback((void*)&obj, (fGenericCBFunc)TimeSyncCallback);
  1854. pRendInfo->m_pStream = pStream;
  1855. pRendInfo->m_pStream->AddRef();
  1856. if (m_ulSourceDuration < pStreamInfo->m_ulDuration)
  1857. {
  1858.     m_ulSourceDuration = pStreamInfo->m_ulDuration;
  1859. }
  1860.     
  1861. if (pRendInfo->m_pTimeSyncCallback)
  1862. {
  1863.     pRendInfo->m_pTimeSyncCallback->AddRef();
  1864. }
  1865. else
  1866. {
  1867.     theErr = HXR_OUTOFMEMORY;
  1868.     GOTOEXITONERROR(theErr, exit);
  1869. }
  1870. m_pRendererMap->SetAt(pStreamInfo->m_uStreamNumber, (void*) pRendInfo);
  1871. if (pStream)
  1872. {
  1873.     if (pStream->IsSureStream())
  1874.     {
  1875. pSource->m_bSureStreamClip = TRUE;
  1876.     }
  1877.     pSource->AddHXStream(pStream);
  1878.     HX_RELEASE(pStream);
  1879. }
  1880.     }
  1881. exit:
  1882.     HX_RELEASE(pStream);
  1883.     HX_RELEASE(pHeader);
  1884.     if (!theErr)
  1885.     {
  1886. m_bAreStreamsSetup = TRUE;
  1887.     }
  1888.     return theErr;
  1889. }
  1890. RendererInfo* 
  1891. SourceInfo::NewRendererInfo()
  1892. {
  1893.     return (new RendererInfo());
  1894. }
  1895. HX_RESULT
  1896. SourceInfo::SetupRenderer(RendererInfo*& pRendInfo, IHXRenderer*& pRenderer, 
  1897.  STREAM_INFO*& pStreamInfo, HXStream*& pStream)
  1898. {
  1899.     HX_RESULT       theErr              = HXR_OK;
  1900.     ULONG32         ulSyncGranularity   = DEFAULT_TIMESYNC_GRANULARITY;
  1901.     BOOL     bLiveSource = FALSE;
  1902.     HXSource*      pSource             = m_pSource;
  1903.     IHXPlugin*     pPlugin             = NULL;
  1904.     STREAM_INFO*    pSrcStreamInfo = NULL;
  1905.     IHXStatistics* pStatistics = NULL;
  1906.     const char**    ppTmpMimeType = 0;
  1907.     pRendInfo->m_pRenderer          = pRenderer;
  1908.     if (HXR_OK != pRenderer->QueryInterface(IID_IHXPlugin,(void**)&pPlugin))
  1909.     {
  1910. theErr = HXR_NOT_INITIALIZED;
  1911.     }
  1912.     else
  1913.     {
  1914. /* Initialize the plugin for use */
  1915. if (HXR_OK != pPlugin->InitPlugin((IUnknown*) (IHXStreamSource*) m_pSource))
  1916. {
  1917.     theErr = HXR_NOT_INITIALIZED;
  1918. }
  1919. pPlugin->Release();
  1920.     }
  1921.     GOTOEXITONERROR(theErr, exit);
  1922. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1923.     if (HXR_OK == pRenderer->QueryInterface(IID_IHXStatistics, (void**) &pStatistics))
  1924.     {
  1925. if (HXR_OK == pSource->GetStreamInfo(pRendInfo->m_pStreamInfo->m_uStreamNumber, pSrcStreamInfo) &&
  1926.     pSrcStreamInfo && pSrcStreamInfo->m_pStats)
  1927. {
  1928.     pStatistics->InitializeStatistics(pSrcStreamInfo->m_pStats->m_pRenderer->m_ulRegistryID);
  1929. }
  1930. HX_RELEASE (pStatistics);
  1931.     }
  1932. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1933.     theErr = pRenderer->StartStream(pStream, m_pPlayer);
  1934.     GOTOEXITONERROR(theErr, exit);
  1935.     theErr = pRenderer->OnHeader(pStreamInfo->m_pHeader);
  1936.     GOTOEXITONERROR(theErr, exit);
  1937.     // start the stream
  1938.     /* get the minimum granularity */
  1939.     pRenderer->GetRendererInfo(ppTmpMimeType, ulSyncGranularity);
  1940.     /* sanity check */
  1941.     if (ulSyncGranularity < MINIMUM_TIMESYNC_GRANULARITY)
  1942.     {
  1943. ulSyncGranularity = MINIMUM_TIMESYNC_GRANULARITY;
  1944.     }
  1945.     if (ulSyncGranularity < m_pPlayer->m_ulLowestGranularity)
  1946.     {
  1947. m_pPlayer->m_ulLowestGranularity = ulSyncGranularity;
  1948.     }
  1949.     // get properties of the header
  1950.     pStreamInfo->m_ulDelay       = m_pSource->GetDelay();
  1951.     pRendInfo->m_ulGranularity      = ulSyncGranularity;
  1952.     pRendInfo->m_ulDuration         = pStreamInfo->m_ulDuration;
  1953.     // OnHeader may have overriddden the m_ulPreroll from the stream header
  1954.     // if it was too big or too small or not set.
  1955.     ULONG32 ulPreroll;
  1956.     if (HXR_OK == pStreamInfo->m_pHeader->GetPropertyULONG32("Preroll", ulPreroll))
  1957.     {
  1958. pStreamInfo->BufferingState().SetPreroll(ulPreroll);
  1959.     }
  1960.     // check if renderer is interrupt safe
  1961.     IHXInterruptSafe* pInterruptSafe;
  1962.     if (HXR_OK == pRenderer->QueryInterface(IID_IHXInterruptSafe,(void**)&pInterruptSafe))
  1963.     {
  1964. HX_ASSERT(pInterruptSafe) ;
  1965. if (pInterruptSafe)
  1966. {
  1967.     pRendInfo->m_bInterruptSafe = pInterruptSafe->IsInterruptSafe();
  1968.     pInterruptSafe->Release();
  1969. }
  1970.     }    
  1971.     
  1972.     m_pPlayer->m_bResumeOnlyAtSystemTime |= (!pRendInfo->m_bInterruptSafe);
  1973.     
  1974.     /* Enter to the begin list so that we can call Begin at the right time */
  1975.     m_pPlayer->EnterToBeginList(pRendInfo);
  1976.     // notify the persistent renderer(source) who implements
  1977.     // IHXRendererAdviseSink to monitor the status of its tracks
  1978.     if (m_pRendererAdviseSink && pStream && !m_bIsPersistentSource)
  1979.     {
  1980. bLiveSource = pSource->IsLive();
  1981. if (m_bIndefiniteDuration)
  1982. {
  1983.     m_ulTrackDuration = MAX_UINT32;
  1984. }
  1985. else
  1986. {
  1987.     m_ulTrackDuration = m_pSource->GetDuration();
  1988. }
  1989. if (!m_bIsTrackDurationSet)
  1990. {     
  1991.     m_bIsTrackDurationSet = TRUE;
  1992.     m_pRendererAdviseSink->TrackDurationSet(m_uGroupID,
  1993.     m_uTrackID,
  1994.     m_ulTrackDuration,
  1995.     pStreamInfo->m_ulDelay,
  1996.     bLiveSource);
  1997. }
  1998.     }
  1999.     if (m_pRendererAdviseSink && pStream)
  2000.     {
  2001. IUnknown* pUnk = 0;
  2002. if(HXR_OK == pStream->QueryInterface(IID_IUnknown, (void**)&pUnk))
  2003. {
  2004.     /* 
  2005.      * construct the IHXValues info for the RendererInitialized call
  2006.      */
  2007.     IHXValues* pValues = new CHXHeader;
  2008.     pValues->AddRef();
  2009.     pValues->SetPropertyULONG32("GroupIndex", m_uGroupID);
  2010.     pValues->SetPropertyULONG32("TrackIndex", m_uTrackID);
  2011.     pValues->SetPropertyULONG32("Delay", pStreamInfo->m_ulDelay);
  2012.     
  2013.     /* We should really fix SMIL renderer to look at MAX duration
  2014.      * For now, we will pass max duration for all the renderers.
  2015.      * The only case where the duration is different is with image maps 
  2016.      * in video/audio stream.
  2017.      */
  2018.     pValues->SetPropertyULONG32("Duration", m_ulTrackDuration);     
  2019.     pValues->SetPropertyULONG32("LiveSource", bLiveSource);
  2020.     if (!m_id.IsEmpty())
  2021.     {
  2022.      IHXBuffer* pBuffer = new CHXBuffer();
  2023. pBuffer->AddRef();
  2024.     
  2025. pBuffer->Set((const UCHAR*)(const char*)m_id, m_id.GetLength()+1);
  2026. pValues->SetPropertyCString("id", pBuffer);
  2027. HX_RELEASE(pBuffer);
  2028.     }
  2029.     HX_RESULT rc = m_pRendererAdviseSink->RendererInitialized(pRenderer, pUnk, pValues);
  2030.     pValues->Release();
  2031.     pUnk->Release();
  2032. }
  2033.     }
  2034.     // XXX HP we need to re-examine how the SMIL renderer's layout site 
  2035.     // setup work!!
  2036.     if (m_bIsPersistentSource)
  2037.     {
  2038. m_pPlayer->m_bSetupLayoutSiteGroup = FALSE;
  2039.     }
  2040. exit:
  2041.     return theErr;
  2042. }
  2043. HX_RESULT
  2044. SourceInfo::InitializeAndSetupRendererSites()
  2045. {
  2046.     HX_RESULT theErr = HXR_OK;
  2047.     BOOL bInitialized = FALSE;
  2048.     if (HXR_OK != m_lastError)
  2049.     {
  2050.         return m_lastError;
  2051.     }
  2052.     if (m_bLocked)
  2053.     {
  2054. return HXR_OK;
  2055.     }
  2056.     m_bLocked = TRUE;
  2057.     m_pMutex->Lock();
  2058.     theErr = InitializeRenderers(bInitialized);
  2059.     if (!theErr && m_bInitialized)
  2060.     {
  2061. /* This source may have audio streams */
  2062. if (!m_pPlayer->m_ulMinimumAudioPreroll)
  2063. {
  2064.     m_pPlayer->m_ulMinimumAudioPreroll = 
  2065. m_pPlayer->m_pAudioPlayer->GetInitialPushdown();
  2066. }
  2067. UINT32 ulMinimumStartingPreroll = m_pPlayer->m_pAudioPlayer->GetInitialPushdown(TRUE);
  2068. m_pSource->SetMinimumPreroll(m_pPlayer->m_ulMinimumAudioPreroll, ulMinimumStartingPreroll);
  2069. #if defined(HELIX_FEATURE_VIDEO)
  2070. /* Set all the renderer sites */
  2071. SetupRendererSites(!m_pPlayer->m_bSetupLayoutSiteGroup);
  2072. /* Did we have to call BeginChangeLayout? */
  2073. if (m_pPlayer->m_pSiteSupplier && 
  2074.     !m_pPlayer->m_bBeginChangeLayoutTobeCalled &&
  2075.     // XXX HP we will not call DoneChangeLayout on persistent source until
  2076.     //       the actual source has been initialized. this fixed the resizing
  2077.     //       problem during stop/play on SMIL in RAM
  2078.     //       the other DoneChangeLayout in HXPlayer won't be called either
  2079.     //       since we set m_bSetupLayoutSiteGroup=FALSE in SetupRenderer() of
  2080.     //       the persistent source
  2081.     !m_bIsPersistentSource)
  2082. {
  2083.     /*
  2084.      * At this point all renderers are layed out!
  2085.      */
  2086.     m_pPlayer->m_bBeginChangeLayoutTobeCalled = TRUE;
  2087.     m_pPlayer->m_pSiteSupplier->DoneChangeLayout();
  2088. }
  2089. #endif /* HELIX_FEATURE_VIDEO */
  2090. if (m_pSource->TryResume())
  2091. {
  2092.     m_pPlayer->RegisterSourcesDone();
  2093. }
  2094. Begin();
  2095.     }
  2096.     if (HXR_OK != theErr && HXR_OK == m_lastError)
  2097.     {
  2098.         m_lastError = theErr;
  2099.     }
  2100.     m_pMutex->Unlock();
  2101.     m_bLocked = FALSE;
  2102.     return theErr;
  2103. }
  2104. void
  2105. SourceInfo::RenderersCleanup()
  2106. {
  2107.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  2108.     for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  2109.     {
  2110. RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  2111. LONG32       lStreamNumber = ndxRend.get_key();
  2112. if(m_pRendererAdviseSink && pRendInfo->m_pRenderer)
  2113. {
  2114.     IHXValues* pValues = new CHXHeader;
  2115.     pValues->AddRef();
  2116.     pValues->SetPropertyULONG32("GroupIndex", m_uGroupID);
  2117.     pValues->SetPropertyULONG32("TrackIndex", m_uTrackID);
  2118.     pValues->SetPropertyULONG32("StreamNumber", lStreamNumber);
  2119.     if (!m_id.IsEmpty())
  2120.     {
  2121.      IHXBuffer* pBuffer = new CHXBuffer();
  2122. pBuffer->AddRef();
  2123.     
  2124. pBuffer->Set((const UCHAR*)(const char*)m_id, m_id.GetLength()+1);
  2125. pValues->SetPropertyCString("id", pBuffer);
  2126. HX_RELEASE(pBuffer);
  2127.     }
  2128.     m_pRendererAdviseSink->RendererClosed(pRendInfo->m_pRenderer, pValues);
  2129.     pValues->Release();
  2130. }
  2131. // remove all the packets associated with this renderer
  2132. LISTPOSITION lPos = m_pPlayer->m_EventList.GetHeadPosition();
  2133. while(lPos && m_pPlayer->m_EventList.GetCount())
  2134. {     
  2135.     CHXEvent* pEvent = (CHXEvent*)m_pPlayer->m_EventList.GetAt(lPos);
  2136.     
  2137.     if (pEvent->m_pRendererInfo == pRendInfo)
  2138.     {
  2139. HX_DELETE(pEvent);
  2140. lPos = m_pPlayer->m_EventList.RemoveAt(lPos);
  2141.     }
  2142.     else
  2143.     {
  2144. m_pPlayer->m_EventList.GetNext(lPos);
  2145.     }
  2146. }
  2147. RenderersCleanupExt(pRendInfo);
  2148. HX_RELEASE(pRendInfo->m_pRenderer);
  2149. HX_RELEASE(pRendInfo->m_pRendererEnumerator);
  2150. HX_DELETE(pRendInfo);
  2151.     }
  2152.     if (m_pCurrentScheduleList)
  2153.     {
  2154. m_pCurrentScheduleList->RemoveAll();
  2155.     }
  2156.     m_pRendererMap->RemoveAll();
  2157.     return;
  2158. }
  2159. void
  2160. SourceInfo::RenderersCleanupExt(RendererInfo* pRendInfo)
  2161. {
  2162.     return;
  2163. }
  2164. HX_RESULT
  2165. SourceInfo::CloseRenderers()
  2166. {
  2167.     if (m_bActive)
  2168.     {
  2169. m_bActive = FALSE;
  2170. m_pPlayer->m_uNumSourcesActive--;
  2171.     }
  2172.     // persistent source will be closed by the persistent manager
  2173.     if (m_bIsPersistentSource)
  2174.     {
  2175. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2176.         //Move this reg tree to a different place.
  2177.         m_pPlayer->UpdatePersistentSrcInfo(this,
  2178.                                            m_pPlayer->m_pStats->m_ulRegistryID,
  2179.                                            m_uTrackID);
  2180. #endif        
  2181. return HXR_FAIL;
  2182.     }
  2183.     // This way the source will still be around until the
  2184.     // renderers are closed.
  2185.     HX_RELEASE(m_pSource);
  2186.     RenderersCleanup();
  2187.     HX_RELEASE(m_pRendererAdviseSink);
  2188.     return HXR_OK;
  2189. }
  2190. HX_RESULT 
  2191. SourceInfo::OnTimeSync(ULONG32 ulCurrentTime)
  2192. {
  2193.     HX_RESULT theErr = HXR_OK;
  2194. //{FILE* f1 = ::fopen("d:\temp\audio.txt", "a+"); ::fprintf(f1, "SourceInfo::OnTimeSync: %lun", ulCurrentTime);::fclose(f1);}
  2195.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  2196.     for (; !theErr && ndxRend != m_pRendererMap->End(); ++ndxRend)
  2197.     {
  2198. RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  2199. /* It is OK to send time sync within +TIME_SYNC_FUDGE_FACTOR */
  2200. if (!pRendInfo->m_bInitialBeginToBeSent &&
  2201.     pRendInfo->m_ulNextDueSyncTime <=
  2202.     ulCurrentTime + TIME_SYNC_FUDGE_FACTOR &&
  2203.     (m_pSource->IsLive() || ulCurrentTime <= pRendInfo->m_ulDuration ||
  2204.     !pRendInfo->m_bDurationTimeSyncSent ||
  2205.      (m_bIsPersistentSource && !m_bActive)))
  2206. {
  2207.     m_pPlayer->m_pScheduler->Remove(
  2208.              pRendInfo->m_pTimeSyncCallback->GetPendingCallback());
  2209.         
  2210.             pRendInfo->m_pTimeSyncCallback->CallbackCanceled();
  2211.     
  2212.             theErr = OnTimeSync(pRendInfo, TRUE);
  2213.     if(m_pPlayer->m_bCurrentPresentationClosed)
  2214.     {
  2215. goto exit;
  2216.     }
  2217. }
  2218.     }
  2219. exit:
  2220.     return theErr;
  2221. }
  2222. HX_RESULT    
  2223. SourceInfo::OnTimeSync(RendererInfo* pRendInfo, BOOL bUseCurrentTime)
  2224. {
  2225.     HX_RESULT theErr = HXR_OK;
  2226.     if (m_bLocked)
  2227.     {
  2228. return HXR_OK;
  2229.     }
  2230.     m_bLocked = TRUE;
  2231.     m_pMutex->Lock();
  2232.     // no OnTimeSync() when the source(track) is paused
  2233.     if (!m_pSource || m_pSource->IsPaused())
  2234.     {
  2235. m_pMutex->Unlock();
  2236. m_bLocked = FALSE;
  2237. return HXR_OK;
  2238.     }
  2239.     if (!m_pPlayer->m_bInitialized)
  2240.     {
  2241. m_pMutex->Unlock();
  2242. m_bLocked = FALSE;
  2243. return HXR_NOT_INITIALIZED;
  2244.     }
  2245.     m_pPlayer->m_bCurrentPresentationClosed = FALSE;
  2246.     /* Do we query for the current time?
  2247.      * This routine may be called as a callback (where we want to find
  2248.      * out the current time) OR can be called for all DUE renderers
  2249.      * whenevr we get a timesync (here we do not want to call getcurrenttime()
  2250.      * again)
  2251.      *
  2252.      * Changed to: (on 09/05/1998 --RA) 
  2253.      *
  2254.      * Always ask the audio services what the current time is. This is 
  2255.      * because we do not make system call in this function anymore to get the 
  2256.      * audio device time. Instead, we use realtime to adjust the
  2257.      * last audio time returned by the device.
  2258.      */
  2259.     m_pPlayer->m_ulCurrentPlayTime = 
  2260. m_pPlayer->m_pAudioPlayer->GetCurrentPlayBackTime();
  2261.     if (m_pPlayer->m_bIsFirstTimeSync)
  2262.     {
  2263. m_pPlayer->m_bIsFirstTimeSync  = FALSE;
  2264. m_pPlayer->m_ulFirstTimeSync   = m_pPlayer->m_ulCurrentPlayTime;
  2265.     }
  2266.     /*
  2267.      * Call ProcessCurrentEvents ONLY if we are here form a scheduled
  2268.      * timesync callback. If we are here from HXPlayer::OnTimeSync, we
  2269.      * should have already called ProcessCurrentEvents in HXPlayer.
  2270.      */
  2271.     if (!bUseCurrentTime)
  2272.     {
  2273. theErr  = m_pPlayer->ProcessCurrentEvents();
  2274.     }
  2275.     /* Duration check */
  2276.     ULONG32 ulCurrentPlayTime = m_pPlayer->m_ulCurrentPlayTime;
  2277. //{FILE* f1 = ::fopen("c:\temp\sync.txt", "a+"); ::fprintf(f1, "SourceInfo::OnTimeSync: Renderer: %p %lun", pRendInfo->m_pRenderer, ulCurrentPlayTime);::fclose(f1);}
  2278.     IHXRenderer* lRend         = (IHXRenderer*) pRendInfo->m_pRenderer;
  2279.     STREAM_INFO*  pStreamInfo   = pRendInfo->m_pStreamInfo;
  2280.     
  2281.     if (m_pSource->isRestrictedLiveStream() && 
  2282. ulCurrentPlayTime > pRendInfo->m_ulDuration)
  2283.     {
  2284. // mark all the streams done if one of the streams is done
  2285. if (!pStreamInfo->m_bSrcInfoStreamDone)
  2286. {
  2287.     pStreamInfo->m_bSrcInfoStreamDone = TRUE;
  2288.     pStreamInfo->ResetPostEndTimeEventList();
  2289.     if (!pStreamInfo->m_bSrcInfoStreamFillingDone)
  2290.     {
  2291. pStreamInfo->m_bSrcInfoStreamFillingDone = TRUE;
  2292.     }
  2293. }
  2294. CheckIfDone();
  2295. goto exit;
  2296.     }
  2297.     if (m_pSource)
  2298.     {
  2299. theErr = m_pSource->OnTimeSync(ulCurrentPlayTime);
  2300.     }
  2301.     /* if we were in a seek state before, we need to send a postseekmessage
  2302.      * before sending timesync...
  2303.      */
  2304.     /* We should probably not do this since there may be Pre-Seek Packets for
  2305.      * some renderers that have not been sent yet since they are not
  2306.      * interrup safe.
  2307.      */
  2308.     /*
  2309.     if (pRendInfo->m_BufferingReason == BUFFERING_SEEK || 
  2310. pRendInfo->m_BufferingReason == BUFFERING_LIVE_PAUSE)
  2311.     {
  2312. pRendInfo->m_BufferingReason   = BUFFERING_CONGESTION;
  2313. lRend->OnPostSeek(pStreamInfo->m_ulTimeBeforeSeek,
  2314.   pStreamInfo->m_ulTimeAfterSeek);
  2315.     }
  2316.     */
  2317.     /* We only want to send time sync if it is greater than the last time
  2318.      * sync sent to the renderer
  2319.      */
  2320. //{FILE* f1 = ::fopen("c:\temp\sync.txt", "a+"); ::fprintf(f1, "SourceInfo::OnTimeSync: lastsynctime: %lu currentplaytime: %lun", pRendInfo->m_ulLastSyncTime, ulCurrentPlayTime );::fclose(f1);}
  2321.     if (pRendInfo->m_bIsFirstCallback ||
  2322. pRendInfo->m_ulLastSyncTime < ulCurrentPlayTime)
  2323.     {
  2324. /* tell the renderer what their time should be (not the player's time)
  2325.  * taking into account the source's start time, delay, loop count.
  2326.  */
  2327. UINT32 ulRealtime = ulCurrentPlayTime;
  2328. if (m_pSource->IsLive())
  2329. {
  2330.     /* First TimeSync and received at least one packet */
  2331.     if (pRendInfo->m_bIsFirstTimeSync && !pRendInfo->m_bIsFirstPacket)
  2332.     {
  2333. pRendInfo->m_bIsFirstTimeSync = FALSE;
  2334. pRendInfo->m_bTimeDiffPositive = 
  2335.     (pRendInfo->m_ulStreamStartTime >= 
  2336.     m_pPlayer->m_ulFirstTimeSync);
  2337. // CALCULATE_ELAPSED_TICKS assumes 0 is > 0xf??????? and 
  2338. // since we know it's not in this case we special case it
  2339. if (m_pPlayer->m_ulFirstTimeSync != 0)
  2340. {
  2341.     if (pRendInfo->m_bTimeDiffPositive)
  2342.     {
  2343. pRendInfo->m_ulTimeDiff        = 
  2344. CALCULATE_ELAPSED_TICKS(m_pPlayer->m_ulFirstTimeSync,
  2345. pRendInfo->m_ulStreamStartTime);
  2346.     }
  2347.     else
  2348.     {
  2349. pRendInfo->m_ulTimeDiff        = 
  2350. CALCULATE_ELAPSED_TICKS(pRendInfo->m_ulStreamStartTime,
  2351. m_pPlayer->m_ulFirstTimeSync);
  2352.     }
  2353. }
  2354. else
  2355. {
  2356.     pRendInfo->m_ulTimeDiff        = 
  2357. pRendInfo->m_ulStreamStartTime;
  2358. }
  2359.     }
  2360.     if (pRendInfo->m_bTimeDiffPositive)
  2361.     {
  2362.         ulRealtime += pRendInfo->m_ulTimeDiff;
  2363.     }
  2364.     else
  2365.     {
  2366.         ulRealtime -= pRendInfo->m_ulTimeDiff;
  2367.     }
  2368. }
  2369. BOOL bAtInterrupt = m_pPlayer->m_pEngine->AtInterruptTime();
  2370. if (!bAtInterrupt || pRendInfo->m_bInterruptSafe)
  2371. {
  2372.     if (!m_bIsPersistentSource && 
  2373. !m_pSource->IsLive() &&
  2374. ulRealtime >= pRendInfo->m_ulDuration)
  2375.     {
  2376. ulRealtime = pRendInfo->m_ulDuration;
  2377.     }
  2378.     theErr = lRend->OnTimeSync(ulRealtime);     
  2379.     if( theErr == HXR_OUTOFMEMORY )
  2380.     {
  2381.         m_pPlayer->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
  2382.     }
  2383.     if( theErr != HXR_OK )
  2384.     {
  2385.         goto exit;
  2386.     }
  2387. #if defined(HELIX_FEATURE_SMIL_REPEAT)
  2388.     // repeat support:
  2389.     // make sure we called OnTimeSync() on the active source
  2390.     // before we tearing down its peer source
  2391.     if (!bAtInterrupt     && 
  2392. m_pPeerSourceInfo   &&
  2393. m_pPeerSourceInfo->m_bRepeatPending)
  2394.     {
  2395. CHXSimpleList*  pRepeatList = m_bLeadingSource?m_pRepeatList:m_pPeerSourceInfo->m_pRepeatList;
  2396. HX_ASSERT(pRepeatList);
  2397. RepeatInfo*     pRepeatInfo = NULL;
  2398. HXSource*     pPeerSource = m_pPeerSourceInfo->m_pSource;
  2399. LISTPOSITION     nextPos = 0;
  2400. // take care repeat="indefinite" when max. duration is set
  2401. if (m_bRepeatIndefinite &&
  2402.     m_ulMaxDuration &&
  2403.     m_pSource->GetDuration() >= m_pSource->m_ulOriginalDelay + m_ulMaxDuration)
  2404. {
  2405.     m_pPeerSourceInfo->Reset();
  2406. }
  2407. // otherwise, prepare for the new repeat
  2408. else
  2409. {
  2410.     if (m_curPosition != pRepeatList->GetTailPosition())
  2411.     {
  2412. nextPos = m_curPosition;
  2413. pRepeatInfo = (RepeatInfo*)pRepeatList->GetAtNext(nextPos);
  2414.     }
  2415.     else if (m_bRepeatIndefinite)
  2416.     {
  2417. nextPos = (RepeatInfo*)pRepeatList->GetHeadPosition();
  2418. pRepeatInfo = (RepeatInfo*)pRepeatList->GetAt(nextPos);
  2419. UINT32 ulDelayTimeOffset = m_pSource->GetDelay() + m_ulRepeatInterval - pRepeatInfo->ulDelay;
  2420. m_pPeerSourceInfo->m_ulRepeatDelayTimeOffset = ulDelayTimeOffset;
  2421. m_ulRepeatDelayTimeOffset = ulDelayTimeOffset;
  2422.     }
  2423.     if (nextPos && pRepeatInfo)
  2424.     {
  2425. m_pPeerSourceInfo->m_curPosition = nextPos;
  2426. // initialize the new repeat
  2427. m_pPeerSourceInfo->m_uTrackID = pRepeatInfo->uTrackID;
  2428. m_pPeerSourceInfo->Reset();
  2429. pPeerSource->ReSetup();
  2430.     }
  2431.     // done with the repeat
  2432.     else
  2433.     {
  2434. m_pPeerSourceInfo->Reset();
  2435.     }
  2436. }
  2437. m_pPeerSourceInfo->m_bRepeatPending = FALSE;
  2438.     }
  2439. #endif /* HELIX_FEATURE_SMIL_REPEAT */
  2440.     if ((UINT32) ulRealtime >= pRendInfo->m_ulDuration && pRendInfo->m_bOnEndOfPacketSent)
  2441.     {
  2442. pRendInfo->m_bDurationTimeSyncSent = TRUE;
  2443.     }
  2444. }
  2445. else 
  2446. {
  2447.     if (!pRendInfo->m_pTimeSyncCallback->GetPendingCallback())
  2448.     {
  2449.                 pRendInfo->m_pTimeSyncCallback->CallbackScheduled(
  2450.                  m_pPlayer->m_pScheduler->RelativeEnter(pRendInfo->m_pTimeSyncCallback, 0));
  2451. //{FILE* f1 = ::fopen("c:\temp\ts.txt", "a+"); ::fprintf(f1, "%p ADDING IMMEDIATE TimeSyncCallback: Handle: %lu Thread: %lun", pRendInfo->m_pTimeSyncCallback, (UINT32) pRendInfo->m_PendingHandle, GetCurrentThreadId());::fclose(f1);}
  2452.     }
  2453.     goto exit;
  2454. }
  2455. if(m_pPlayer->m_bCurrentPresentationClosed)
  2456. {
  2457.     goto exit;
  2458. }
  2459. pRendInfo->m_ulLastSyncTime = ulCurrentPlayTime;
  2460.     }
  2461.     /* Do we need to send more timesyncs */
  2462.     if (m_pSource->IsLive() || !pRendInfo->m_bDurationTimeSyncSent ||
  2463. (m_bIsPersistentSource && !m_bActive))
  2464.     {
  2465. ULONG32 ulNextCBTime = pRendInfo->m_ulGranularity;
  2466. /* Do we need to increment our next due time sync value?
  2467.  * This check is needed since a lot of WOM_DONEs may get accumulated
  2468.  * and by the time we end up getting the time sync,
  2469.  * we have already played a bunch of data thereby resulting in a
  2470.  * jump in current audio time.
  2471.  * So we only increment next due time sync if the audio clock is
  2472.  * also moving
  2473.  */
  2474. if (pRendInfo->m_ulNextDueSyncTime  <
  2475.     ulCurrentPlayTime + pRendInfo->m_ulGranularity)
  2476. {
  2477.     pRendInfo->m_ulNextDueSyncTime  += pRendInfo->m_ulGranularity;
  2478. }
  2479. /* We wanna reset ourself if its either the first callback OR
  2480.  * somehow we are lagging behind in the timesyncs
  2481.  */
  2482. if (pRendInfo->m_bIsFirstCallback ||
  2483.     pRendInfo->m_ulNextDueSyncTime < pRendInfo->m_ulLastSyncTime)
  2484. {
  2485.     pRendInfo->m_bIsFirstCallback = FALSE;
  2486.     HXTimeval lTime = m_pPlayer->m_pScheduler->GetCurrentSchedulerTime();
  2487.     pRendInfo->m_pTimeSyncCBTime->tv_sec = lTime.tv_sec;
  2488.     pRendInfo->m_pTimeSyncCBTime->tv_usec = lTime.tv_usec;
  2489.     pRendInfo->m_ulNextDueSyncTime  = pRendInfo->m_ulLastSyncTime +
  2490.       pRendInfo->m_ulGranularity;
  2491.     /* Next due time sync at integral multiple of granularity */
  2492.     ULONG32 ulTimeDiff = pRendInfo->m_ulNextDueSyncTime % pRendInfo->m_ulGranularity;
  2493.     pRendInfo->m_ulNextDueSyncTime -= ulTimeDiff;
  2494.     ulNextCBTime -= ulTimeDiff;
  2495. }
  2496. if (pRendInfo->m_ulNextDueSyncTime > pRendInfo->m_ulDuration &&
  2497.     (!m_bIsPersistentSource && m_bActive) && !m_pSource->IsLive())
  2498. {
  2499.     ULONG32 ulDiff = pRendInfo->m_ulNextDueSyncTime - pRendInfo->m_ulDuration;
  2500.     if (ulNextCBTime > ulDiff)
  2501.     {
  2502. ulNextCBTime -= ulDiff;
  2503.     }
  2504.     pRendInfo->m_ulNextDueSyncTime = pRendInfo->m_ulDuration;
  2505. }
  2506. *(pRendInfo->m_pTimeSyncCBTime) += (int) (ulNextCBTime*1000);
  2507. if (!pRendInfo->m_pTimeSyncCallback->GetPendingCallback())
  2508. {
  2509.     UINT32 ulSchedTime = 0;
  2510.     if (pRendInfo->m_ulNextDueSyncTime > ulCurrentPlayTime)
  2511.     {
  2512. ulSchedTime = pRendInfo->m_ulNextDueSyncTime - ulCurrentPlayTime;
  2513.     }
  2514.     pRendInfo->m_pTimeSyncCallback->CallbackScheduled(
  2515.              m_pPlayer->m_pScheduler->RelativeEnter(pRendInfo->m_pTimeSyncCallback, ulSchedTime));
  2516. }
  2517.     }
  2518. exit:
  2519.     m_pMutex->Unlock();
  2520.     m_bLocked = FALSE;
  2521.     return theErr;
  2522. }
  2523. void
  2524. SourceInfo::Resumed()
  2525. {
  2526.     if (m_bTobeInitializedBeforeBegin)
  2527.     {
  2528. m_bTobeInitializedBeforeBegin = FALSE;
  2529. if (m_pPlayer->m_uNumSourceToBeInitializedBeforeBegin > 0)
  2530. {
  2531.     m_pPlayer->m_uNumSourceToBeInitializedBeforeBegin--;
  2532. }
  2533.     }
  2534. }
  2535. void
  2536. SourceInfo::UpdateDuration(UINT32 ulDuration)
  2537. {
  2538.     m_ulTotalTrackDuration = m_ulTrackDuration = m_ulSourceDuration = ulDuration;
  2539.     if (m_pPeerSourceInfo)
  2540.     {
  2541. m_pPeerSourceInfo->m_ulTotalTrackDuration = m_ulTotalTrackDuration;
  2542.     }
  2543.     CHXMapLongToObj::Iterator i = m_pRendererMap->Begin();
  2544.     for (; i != m_pRendererMap->End(); ++i)
  2545.     {
  2546. RendererInfo* pRendInfo = (RendererInfo*)(*i);
  2547. IHXUpdateProperties* pUpdateProperties = NULL;
  2548. if (pRendInfo->m_pRenderer &&
  2549.     HXR_OK == pRendInfo->m_pRenderer->QueryInterface(IID_IHXUpdateProperties,
  2550.      (void**)&pUpdateProperties))
  2551. {
  2552.     IHXValues* pValues = new CHXHeader();
  2553.     pValues->AddRef();
  2554.     pValues->SetPropertyULONG32("End", m_pSource->GetEndTime());
  2555.     pValues->SetPropertyULONG32("Duration", ulDuration);
  2556.     pUpdateProperties->UpdatePlayTimes(pValues);
  2557.     HX_RELEASE(pValues);
  2558. }
  2559. HX_RELEASE(pUpdateProperties);
  2560. pRendInfo->m_ulDuration = ulDuration;
  2561. pRendInfo->m_pStreamInfo->m_ulDuration = ulDuration;
  2562.     }
  2563.     m_pPlayer->AdjustPresentationTime();
  2564. }
  2565. void
  2566. SourceInfo::UpdateDelay(UINT32 ulDelay)
  2567. {
  2568.     INT32   lOffset = 0;
  2569.     UINT32  ulStartTime = 0;
  2570.     UINT32  ulDuration = 0;
  2571.     ulStartTime = m_pSource->GetStartTime();
  2572.     ulDuration = GetActiveDuration();
  2573.     CHXMapLongToObj::Iterator i = m_pRendererMap->Begin();
  2574.     for (; i != m_pRendererMap->End(); ++i)
  2575.     {
  2576. RendererInfo* pRendInfo = (RendererInfo*)(*i);
  2577. lOffset = ulDelay - pRendInfo->m_pStreamInfo->m_ulDelay;
  2578. // adjust the packet time offset within the core
  2579. LISTPOSITION lPos = m_pPlayer->m_EventList.GetHeadPosition();
  2580. while(lPos)
  2581. {     
  2582.     CHXEvent* pEvent = (CHXEvent*)m_pPlayer->m_EventList.GetNext(lPos);
  2583.     
  2584.     if (pEvent->m_pRendererInfo == pRendInfo)
  2585.     {
  2586. pEvent->SetTimeOffset(ulStartTime - ulDelay); 
  2587.     }
  2588. }
  2589. // adjust the packet time offset within the renderer
  2590. IHXUpdateProperties* pUpdateProperties = NULL;
  2591. if (pRendInfo->m_pRenderer &&
  2592.     HXR_OK == pRendInfo->m_pRenderer->QueryInterface(IID_IHXUpdateProperties,
  2593.      (void**)&pUpdateProperties))
  2594. {
  2595.     pUpdateProperties->UpdatePacketTimeOffset(lOffset);
  2596. }
  2597. HX_RELEASE(pUpdateProperties);
  2598. pRendInfo->m_pStreamInfo->m_ulDelay = ulDelay;
  2599. pRendInfo->m_ulDuration = ulDuration;
  2600. pRendInfo->m_pStreamInfo->m_ulDuration = ulDuration;
  2601.     }
  2602.     m_pPlayer->AdjustPresentationTime();
  2603. }
  2604. #ifdef SEQ_DEPENDENCY
  2605. void
  2606. SourceInfo::SetDependency(IHXBuffer* pDependency)
  2607. {
  2608.     char* pTemp = = new char[pDependency->GetSize()+1];
  2609.     strcpy(pTemp, pDependency->GetBuffer()); /* Flawfinder: ignore */
  2610.     UINT16 i = 0;
  2611.     
  2612.     m_uNumDependencies = 1;
  2613.     /* Find the number of dependencies */
  2614.     while(pTemp[i])
  2615.     {
  2616. if (pTemp[i] == '.')
  2617. {
  2618.     m_uNumDependencies++;
  2619. }
  2620. i++;
  2621.     }
  2622.     m_pDependNode = new UINT16[m_uNumDependencies];
  2623.     char* pNode = strtok(pTemp, ".");
  2624.     /* At least one node should be present */
  2625.     HX_ASSERT(pNode);
  2626.     i = 0;
  2627.     while(pNode)
  2628.     {
  2629. m_pDependNode[i++] = atoi(pNode);
  2630. pNode = strtok(NULL, ".");
  2631.     }
  2632.     HX_ASSERT(i == m_uNumDependencies);
  2633.     HX_VECTOR_DELETE(pTemp);
  2634. }
  2635. #endif /*SEQ_DEPENDENCY*/
  2636. BOOL
  2637. SourceInfo::IsRebufferDone(void)
  2638. {
  2639.     BOOL     bResult = TRUE;
  2640.     RendererInfo*   pRendInfo = NULL;
  2641.     if (m_pSource && m_pSource->m_bRebufferingRequired)
  2642.     {
  2643. CHXMapLongToObj::Iterator i = m_pRendererMap->Begin();
  2644. for (; i != m_pRendererMap->End(); ++i)
  2645. {
  2646.     pRendInfo = (RendererInfo*)(*i);
  2647.     
  2648.     if (!pRendInfo->m_bOnEndOfPacketSent)
  2649.     {
  2650. bResult = FALSE;
  2651. break;
  2652.     }
  2653. }
  2654.     }
  2655.     return bResult;
  2656. }
  2657. void
  2658. SourceInfo::ReInitializeStats()
  2659. {
  2660.     if (!m_bInitialized)
  2661.     {
  2662. return;
  2663.     }
  2664. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  2665.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  2666.     for (UINT16 i = 0; ndxRend != m_pRendererMap->End(); ++ndxRend, i++)
  2667.     {
  2668. RendererInfo* pRendInfo = (RendererInfo*)(*ndxRend);
  2669. HX_ASSERT(pRendInfo->m_pRenderer);
  2670. if (!pRendInfo->m_pRenderer)
  2671. {
  2672.     return;
  2673. }
  2674. IHXStatistics* pStatistics = NULL;
  2675. STREAM_INFO*    pSrcStreamInfo  = NULL;
  2676. if (HXR_OK == pRendInfo->m_pRenderer->QueryInterface(IID_IHXStatistics, (void**) &pStatistics))
  2677. {
  2678.     if (HXR_OK == m_pSource->GetStreamInfo(i, pSrcStreamInfo) &&
  2679. pSrcStreamInfo && pSrcStreamInfo->m_pStats &&
  2680. pSrcStreamInfo->m_pStats->m_pRenderer)
  2681.     {
  2682. pStatistics->InitializeStatistics(pSrcStreamInfo->m_pStats->m_pRenderer->m_ulRegistryID);
  2683.     }
  2684.     HX_RELEASE (pStatistics);
  2685. }
  2686.     }
  2687. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  2688. }
  2689. HX_RESULT
  2690. SourceInfo::HandleRedirectRequest(char* pURL)
  2691. {
  2692.     if (m_pPlayer)
  2693.     {
  2694. return m_pPlayer->HandleRedirectRequest(m_uGroupID, m_uTrackID, pURL);
  2695.     }
  2696.     return HXR_FAILED;
  2697. }
  2698. void
  2699. SourceInfo::ScheduleProcessCallback()
  2700. {
  2701.     if (!m_pProcessCallback->GetPendingCallback())
  2702.     {
  2703.         m_pProcessCallback->CallbackScheduled(
  2704.          m_pPlayer->m_pScheduler->RelativeEnter(m_pProcessCallback, 0));
  2705.     }
  2706. }
  2707. void 
  2708. SourceInfo::SetLiveSyncStartTime(HXSource* pSource, RendererInfo* pTmpRendInfo, 
  2709.  UINT32 ulLowestTime)
  2710. {
  2711.     UINT32 ulLiveSyncStartTime = ulLowestTime;
  2712.     INT32  lTimeOffset = pSource->GetStartTime() - pTmpRendInfo->m_pStreamInfo->m_ulDelay;
  2713.     if (pTmpRendInfo->m_pStreamInfo->m_pHeader)
  2714.     {
  2715. if (lTimeOffset < 0)
  2716. {
  2717.     ulLiveSyncStartTime += (UINT32) (-lTimeOffset);
  2718. }
  2719. else
  2720. {
  2721.     if (ulLiveSyncStartTime < (UINT32)lTimeOffset)
  2722.     {
  2723. ulLiveSyncStartTime = 0;
  2724.     }
  2725.     else
  2726.     {
  2727. ulLiveSyncStartTime -= (UINT32)lTimeOffset;
  2728.     }
  2729. }
  2730. pTmpRendInfo->m_pStreamInfo->m_pHeader->SetPropertyULONG32("LiveSyncStartTime", ulLiveSyncStartTime);
  2731.     }
  2732.     return;
  2733. }
  2734. BOOL
  2735. SourceInfo::AllOtherStreamsHaveEnded(STREAM_INFO* pThisStreamInfo)
  2736. {
  2737.     BOOL bResult = TRUE;
  2738.     CHXMapLongToObj::Iterator ndxRend = m_pRendererMap->Begin();
  2739.     for (; ndxRend != m_pRendererMap->End(); ++ndxRend)
  2740.     {
  2741. RendererInfo* pRendInfo     = (RendererInfo*)(*ndxRend);
  2742. STREAM_INFO*  pStreamInfo   = pRendInfo->m_pStreamInfo;
  2743. /* 
  2744.  * check if any other stream is still active.
  2745.  * do not consider other "CanBeStoppedAnyTime" streams
  2746.  * as active streams
  2747.  */
  2748. if (pStreamInfo != pThisStreamInfo &&
  2749.     !pStreamInfo->m_bCanBeStoppedAnyTime &&
  2750.     !pStreamInfo->m_bSrcInfoStreamDone)
  2751. {
  2752.     bResult = FALSE;
  2753.     break;
  2754. }
  2755.     }
  2756.     return bResult;
  2757. }
  2758. HX_RESULT
  2759. SourceInfo::AppendRepeatRequest(UINT16 uTrackID, IHXValues* pTrack)
  2760. {
  2761. #if defined(HELIX_FEATURE_SMIL_REPEAT)
  2762.     HX_RESULT     theErr = HXR_OK;
  2763.     BOOL     bLive = FALSE;
  2764.     BOOL     bDurationSet = FALSE;
  2765.     BOOL     bMaxDurationSet = FALSE;
  2766.     UINT32     ulStart = 0;
  2767.     UINT32     ulEnd = 0;
  2768.     UINT32     ulDelay = 0;
  2769.     UINT32     ulDuration = 0;   
  2770.     UINT32     ulMaxDuration = 0;
  2771.     UINT32     ulRepeatTag = RepeatUnknown;
  2772.     UINT32     ulRepeatInterval = 0;
  2773.     UINT32     ulLastDelay = 0;
  2774.     char     szId[] = "id";
  2775.     char     szStart[] = "Start";
  2776.     char     szEnd[] = "End";
  2777.     char     szDelay[] = "Delay";
  2778.     char     szDuration[] = "Duration";
  2779.     char     szMaxDuration[] = "maxduration";
  2780.     char     szRepeatTag[] = "repeatTag";
  2781.     IHXBuffer*     pBuffer = NULL;
  2782.     RepeatInfo*     pNewRepeatInfo = NULL;
  2783.     HX_ASSERT(m_bLeadingSource);    
  2784.     if (HXR_OK != pTrack->GetPropertyCString(szId, pBuffer))
  2785.     {
  2786. HX_ASSERT(FALSE);
  2787. theErr = HXR_UNEXPECTED;
  2788. goto cleanup;
  2789.     }
  2790.     // repeated sources should share the same start/end timing attributes
  2791.     if (HXR_OK == pTrack->GetPropertyULONG32(szStart,ulStart))
  2792.     {
  2793. HX_ASSERT(ulStart == m_pSource->GetStartTime());
  2794.     }
  2795.     if (HXR_OK == pTrack->GetPropertyULONG32(szEnd,ulEnd))
  2796.     {
  2797. HX_ASSERT(ulEnd == m_pSource->GetEndTime());
  2798.     }
  2799.     if (HXR_OK != pTrack->GetPropertyULONG32(szDelay,ulDelay))
  2800.     {
  2801. HX_ASSERT(FALSE);
  2802. theErr = HXR_UNEXPECTED;
  2803. goto cleanup;
  2804.     }
  2805.     
  2806.     ulLastDelay = m_pRepeatList?((RepeatInfo*)m_pRepeatList->GetTail())->ulDelay:m_pSource->GetDelay();
  2807.     if (ulDelay <= ulLastDelay)
  2808.     {
  2809. goto cleanup;
  2810.     }
  2811.     
  2812.     if (HXR_OK == pTrack->GetPropertyULONG32(szDuration,ulDuration))
  2813.     {
  2814. bDurationSet = TRUE;
  2815.     }
  2816.     if (HXR_OK == pTrack->GetPropertyULONG32(szMaxDuration, ulMaxDuration))
  2817.     {
  2818. bMaxDurationSet = TRUE;
  2819.     }
  2820.     
  2821.     // skip this repeat if duration == 0
  2822.     if ((bDurationSet && 0 == ulDuration) ||
  2823. (bMaxDurationSet && 0 == ulMaxDuration))
  2824.     {
  2825. goto durationset;
  2826.     }
  2827.     if (HXR_OK != pTrack->GetPropertyULONG32(szRepeatTag, ulRepeatTag))
  2828.     {
  2829. ulRepeatTag = RepeatUnknown;
  2830.     }
  2831.     if (!m_pRepeatList)
  2832.     {
  2833. m_pRepeatList = new CHXSimpleList();
  2834. pNewRepeatInfo = new RepeatInfo;
  2835. pNewRepeatInfo->ulStart = m_pSource->GetStartTime();
  2836. pNewRepeatInfo->ulEnd = m_pSource->GetEndTime();
  2837. pNewRepeatInfo->ulDelay = m_pSource->GetDelay();
  2838. pNewRepeatInfo->ulDuration = m_pSource->m_ulOriginalDuration;
  2839. pNewRepeatInfo->uTrackID = m_uTrackID;
  2840. m_curPosition = m_pRepeatList->AddHead(pNewRepeatInfo);
  2841.     }
  2842.     pNewRepeatInfo = new RepeatInfo;
  2843.     pNewRepeatInfo->ulStart = ulStart?ulStart:m_pSource->GetStartTime();
  2844.     pNewRepeatInfo->ulEnd = ulEnd?ulEnd:m_pSource->GetEndTime();
  2845.     pNewRepeatInfo->ulDelay = ulDelay;
  2846.     pNewRepeatInfo->uTrackID = uTrackID;
  2847.     // if the duration is set
  2848.     if (bDurationSet)
  2849.     {
  2850. pNewRepeatInfo->ulDuration = ulDuration;
  2851.     }
  2852.     // if max. duration is set, make sure its duration <= ulMaxDuration
  2853.     else if (bMaxDurationSet && ulMaxDuration < m_pSource->m_ulOriginalDuration)
  2854.     {
  2855. pNewRepeatInfo->ulDuration = ulMaxDuration;
  2856.     }
  2857.     // set to its leading source's original duration by default
  2858.     else
  2859.     {
  2860. pNewRepeatInfo->ulDuration = m_pSource->m_ulOriginalDuration;
  2861.     }
  2862.     m_pRepeatList->AddTail(pNewRepeatInfo);
  2863.     if (ulRepeatTag == RepeatIndefiniteOnGroup ||
  2864. ulRepeatTag == RepeatIndefiniteOnMe)
  2865.     {
  2866. m_bRepeatIndefinite = TRUE;     
  2867. ulRepeatInterval = ulDelay - ulLastDelay;
  2868. if (ulRepeatInterval > m_ulRepeatInterval)
  2869. {
  2870.     m_ulRepeatInterval = ulRepeatInterval;
  2871. }
  2872. // recaculate the max. duration for repeat="indefinite"
  2873. if (bMaxDurationSet)
  2874. {     
  2875.     m_ulMaxDuration = ulMaxDuration + m_pSource->m_ulOriginalDuration;
  2876.     ulDuration = ulMaxDuration;
  2877.     if (pNewRepeatInfo->ulDuration > ulMaxDuration)
  2878.     {
  2879. pNewRepeatInfo->ulDuration = ulMaxDuration;
  2880.     }
  2881. }
  2882. else
  2883. {
  2884.     if (ulRepeatTag == RepeatIndefiniteOnGroup)
  2885.     {
  2886. ulDuration = m_pSource->m_ulOriginalDuration;
  2887.     }
  2888.     else
  2889.     {
  2890.      ulDuration = MAX_UINT32;
  2891. bLive = TRUE;
  2892.     }
  2893. }
  2894. if (m_pPeerSourceInfo)
  2895. {
  2896.     m_pPeerSourceInfo->m_bRepeatIndefinite = m_bRepeatIndefinite;
  2897.     m_pPeerSourceInfo->m_ulRepeatInterval = m_ulRepeatInterval;
  2898.     m_pPeerSourceInfo->m_ulMaxDuration = m_ulMaxDuration;
  2899. }
  2900.     }
  2901.     else
  2902.     {
  2903. ulDuration = pNewRepeatInfo->ulDuration;
  2904.     }
  2905. durationset:
  2906.     if (m_pRendererAdviseSink)
  2907.     {
  2908. m_pRendererAdviseSink->RepeatedTrackDurationSet((const char*)pBuffer->GetBuffer(),
  2909. ulDuration,
  2910. bLive);
  2911.     }
  2912. cleanup:
  2913.     HX_RELEASE(pBuffer);
  2914.     return theErr;
  2915. #else
  2916.     return HXR_NOTIMPL;
  2917. #endif /* HELIX_FEATURE_SMIL_REPEAT */
  2918. }
  2919. BOOL
  2920. SourceInfo::IsAdjustSeekNeeded(UINT32 ulSeekTime)
  2921. {
  2922.     BOOL bResult = TRUE;
  2923.     // after the repeated sources
  2924.     if (ulSeekTime > GetActiveDuration())
  2925.     {
  2926. m_pPeerSourceInfo->Reset();
  2927. bResult = FALSE;
  2928.     }
  2929.     // within the active source
  2930.     else if (ulSeekTime >= m_pSource->GetDelay() &&
  2931.      ulSeekTime < m_pSource->GetDuration())
  2932.     {
  2933. bResult = FALSE;
  2934.     }
  2935.     return bResult;
  2936. }
  2937. SourceInfo*
  2938. SourceInfo::DoAdjustSeek(UINT32 ulSeekTime)
  2939. {    
  2940. #if defined(HELIX_FEATURE_SMIL_REPEAT)
  2941.     BOOL     bRepeatDelayTimeOffsetAdjusted = FALSE;
  2942.     UINT32     ulOriginalDuration = 0;
  2943.     UINT32     ulOriginalDelay = 0;
  2944.     UINT32     ulActiveDuration = 0;
  2945.     UINT32     ulRepeatDelayTimeOffset = 0;
  2946.     SourceInfo*     pResult = NULL;
  2947.     RepeatInfo*     pRepeatInfo = NULL;
  2948.     RepeatInfo*     pRepeatInfoHead = NULL;
  2949.     RepeatInfo*     pRepeatInfoTail = NULL;
  2950.     CHXSimpleList*  pRepeatList = NULL;
  2951.     LISTPOSITION    pRepeatPos = 0;
  2952.    
  2953.     pRepeatPos = m_curPosition;
  2954.     ulOriginalDuration = m_pSource->m_ulOriginalDuration;
  2955.     ulOriginalDelay = m_pSource->m_ulOriginalDelay;
  2956.     ulActiveDuration = GetActiveDuration();
  2957.     pRepeatList = m_bLeadingSource?m_pRepeatList:m_pPeerSourceInfo->m_pRepeatList;
  2958.     // within the active source
  2959.     if (ulSeekTime >= m_pSource->GetDelay() &&
  2960. ulSeekTime < m_pSource->GetDuration())
  2961.     {
  2962. pResult = this;
  2963. goto cleanup;
  2964.     }
  2965.     // after the repeated sources(exclude repeat="indefinite")
  2966.     if (!m_bRepeatIndefinite && ulSeekTime > ulActiveDuration)
  2967.     {
  2968. pResult = this;
  2969. goto cleanup;
  2970.     }
  2971.     // end the current source
  2972.     if (!m_pSource->IsSourceDone())
  2973.     {
  2974. m_pSource->SetEndOfClip(TRUE);
  2975.     }
  2976.     m_bDone = TRUE;
  2977.     // seek to the next spawned source
  2978.     if (ulSeekTime >= m_pSource->GetDuration() &&
  2979.         ulSeekTime < m_pPeerSourceInfo->m_pSource->GetDuration())
  2980.     {
  2981. pResult = m_pPeerSourceInfo;
  2982. goto cleanup;
  2983.     }
  2984.     // seek before the repeated source
  2985.     if (ulSeekTime < ulOriginalDelay)
  2986.     {
  2987. pResult = this;
  2988. pResult->m_curPosition = pRepeatList->GetHeadPosition();
  2989. if (pResult->m_ulRepeatDelayTimeOffset != 0)
  2990. {
  2991.     pResult->m_ulRepeatDelayTimeOffset = 0;
  2992.     pResult->m_pPeerSourceInfo->m_ulRepeatDelayTimeOffset = 0;
  2993.     bRepeatDelayTimeOffsetAdjusted = TRUE;
  2994. }
  2995.     }
  2996.     else
  2997.     {
  2998. // need to figure out the exact iteration on repeat indefinite
  2999. if (m_bRepeatIndefinite)
  3000. {
  3001.     pRepeatInfoHead = (RepeatInfo*)pRepeatList->GetHead();
  3002.     pRepeatInfoTail = (RepeatInfo*)pRepeatList->GetTail();
  3003.     
  3004.     ulRepeatDelayTimeOffset = pRepeatInfoTail->ulDelay + m_ulRepeatInterval - pRepeatInfoHead->ulDelay;
  3005. }
  3006. // ahead of the current source
  3007. if (ulSeekTime < m_pSource->GetDelay())
  3008. {
  3009.     if (m_bRepeatIndefinite)
  3010.     {
  3011. // need to figure out the exact iteration on repeat indefinite
  3012. while (m_ulRepeatDelayTimeOffset + pRepeatInfoHead->ulDelay > ulSeekTime)
  3013. {
  3014.     m_ulRepeatDelayTimeOffset -= ulRepeatDelayTimeOffset;
  3015.     bRepeatDelayTimeOffsetAdjusted = TRUE;
  3016. }
  3017. // start from its tail
  3018. if (bRepeatDelayTimeOffsetAdjusted)
  3019. {
  3020.     pRepeatPos = pRepeatList->GetTailPosition();
  3021. }
  3022.     }
  3023.     pRepeatInfo = (RepeatInfo*)pRepeatList->GetAt(pRepeatPos);
  3024.     while (pRepeatPos != pRepeatList->GetHeadPosition())
  3025.     {
  3026. if (ulSeekTime >= (pRepeatInfo->ulDelay + m_ulRepeatDelayTimeOffset))
  3027. {
  3028.     break;
  3029. }
  3030. pRepeatInfo = (RepeatInfo*)pRepeatList->GetAtPrev(pRepeatPos);
  3031.     }
  3032. }
  3033. else
  3034. {               
  3035.     if (m_bRepeatIndefinite)
  3036.     {
  3037. // need to figure out the exact iteration on repeat indefinite
  3038. while (m_ulRepeatDelayTimeOffset + pRepeatInfoTail->ulDelay + ulOriginalDuration <
  3039.        ulSeekTime)
  3040. {
  3041.     m_ulRepeatDelayTimeOffset += ulRepeatDelayTimeOffset;
  3042.     bRepeatDelayTimeOffsetAdjusted = TRUE;
  3043. }
  3044. // start from its head
  3045. if (bRepeatDelayTimeOffsetAdjusted)
  3046. {
  3047.     pRepeatPos = pRepeatList->GetHeadPosition();
  3048. }
  3049.     }
  3050.     pRepeatInfo = (RepeatInfo*)pRepeatList->GetAt(pRepeatPos);
  3051.     while (pRepeatPos != pRepeatList->GetTailPosition())
  3052.     {
  3053. if (ulSeekTime <= (m_ulRepeatDelayTimeOffset + pRepeatInfo->ulDelay + ulOriginalDuration))
  3054. {
  3055.     break;
  3056. }
  3057. pRepeatInfo = (RepeatInfo*)pRepeatList->GetAtNext(pRepeatPos);
  3058.     }
  3059. }
  3060. pResult = m_pPeerSourceInfo;
  3061. pResult->m_curPosition = pRepeatPos;
  3062. pResult->m_bTobeInitializedBeforeBegin = TRUE;
  3063.     }
  3064.     if (bRepeatDelayTimeOffsetAdjusted)
  3065.     {
  3066. pResult->m_ulRepeatDelayTimeOffset = m_ulRepeatDelayTimeOffset;
  3067. pResult->m_pPeerSourceInfo->m_ulRepeatDelayTimeOffset = m_ulRepeatDelayTimeOffset;
  3068. m_pPlayer->AdjustPresentationTime();
  3069.     }
  3070.     pResult->Reset();
  3071.     pResult->m_pSource->ReSetup();
  3072. cleanup:
  3073.     if (pRepeatPos == pRepeatList->GetTailPosition() ||
  3074. ulSeekTime > ulActiveDuration)
  3075.     {
  3076. pResult->m_pPeerSourceInfo->Reset();
  3077.     }
  3078.     pResult->m_bRepeatPending = FALSE;
  3079.     pResult->m_pPeerSourceInfo->m_bRepeatPending = TRUE;
  3080.     if (pResult != this)
  3081.     {
  3082. pResult->m_bSeekPending = TRUE;
  3083. pResult->m_ulSeekTime = ulSeekTime;
  3084.     }
  3085.     return pResult;
  3086. #else
  3087.     return NULL;
  3088. #endif /* HELIX_FEATURE_SMIL_REPEAT */
  3089. }
  3090. UINT32
  3091. SourceInfo::GetActiveDuration()
  3092. {
  3093.     UINT32     ulDuration = 0;
  3094.     RepeatInfo*     pRepeatInfo = NULL;
  3095.     CHXSimpleList*  pRepeatList = m_bLeadingSource?m_pRepeatList:m_pPeerSourceInfo->m_pRepeatList;
  3096.     if (m_ulTotalTrackDuration)
  3097.     {
  3098. return m_ulTotalTrackDuration;
  3099.     }
  3100.     if (pRepeatList)
  3101.     {
  3102. pRepeatInfo = (RepeatInfo*)pRepeatList->GetTail();
  3103. ulDuration = pRepeatInfo->ulDuration + pRepeatInfo->ulDelay + m_ulRepeatDelayTimeOffset;
  3104. if (m_bRepeatIndefinite &&
  3105.     m_ulMaxDuration)
  3106. {
  3107.     ulDuration = m_pSource->m_ulOriginalDelay + m_ulMaxDuration;
  3108. }
  3109.     }
  3110.     else
  3111.     {
  3112. ulDuration = m_pSource->GetDuration();
  3113.     }
  3114.     
  3115.     return ulDuration;
  3116. }
  3117. BOOL
  3118. SourceInfo::KeepSourceActive(void)
  3119. {
  3120.     BOOL bResult = TRUE;
  3121.     CHXSimpleList* pRepeatList = m_bLeadingSource?m_pRepeatList:m_pPeerSourceInfo->m_pRepeatList;
  3122.     
  3123.     if (pRepeatList)
  3124.     {
  3125. // XXX HP re-exam
  3126. // we should keep the repeated source active till the end of its duration
  3127. if (m_bRepeatIndefinite)
  3128. {
  3129.     if (m_ulMaxDuration &&
  3130. m_pSource->GetDuration() >= m_pSource->m_ulOriginalDelay + m_ulMaxDuration)
  3131.     {
  3132. bResult = FALSE;
  3133. goto cleanup;
  3134.     }
  3135. }
  3136. else if (m_curPosition == pRepeatList->GetTailPosition())
  3137. {
  3138.     bResult = FALSE;
  3139.     goto cleanup;
  3140. }
  3141.     }
  3142.     if (m_pPlayer->IsAtSourceMap(this) && 
  3143. !m_pSource->IsPaused() &&
  3144. GetActiveDuration() < m_pPlayer->m_ulCurrentPlayTime)
  3145.     {
  3146. bResult = FALSE;
  3147. goto cleanup;
  3148.     }
  3149. cleanup:
  3150.     return bResult;
  3151. }
  3152. void SourceInfo::TimeSyncCallback(void* pParam)
  3153. {
  3154.     struct timeSyncParamStruct* pObj = (struct timeSyncParamStruct*)pParam;
  3155.     if (pObj)
  3156.     {
  3157.         HX_RESULT theErr = pObj->pSourceInfo->OnTimeSync(pObj->pRenderInfo);
  3158.         //{FILE* f1 = ::fopen("c:\temp\ts.txt", "a+"); ::fprintf(f1, "%p TimeSyncCallback::Func: Before Falsen", this);::fclose(f1);}
  3159.         //{FILE* f1 = ::fopen("c:\temp\ts.txt", "a+"); ::fprintf(f1, "%p TimeSyncCallback::Func: Before OnTimeSyncn", this);::fclose(f1);}
  3160.         //{FILE* f1 = ::fopen("c:\temp\ts.txt", "a+"); ::fprintf(f1, "%p TimeSyncCallback::Func: After OnTimeSyncn", this);::fclose(f1);}
  3161.         if (theErr)
  3162.         {
  3163.             pObj->pSourceInfo->m_pPlayer->Report( HXLOG_ERR, theErr, 0, NULL, NULL );
  3164.         }
  3165.     }
  3166. }
  3167. void SourceInfo::ProcessCallback(void* pParam)
  3168. {
  3169.     HX_RESULT theErr = HXR_OK;
  3170.     SourceInfo* pObj = (SourceInfo*)pParam;
  3171.     if (pObj)
  3172.     {
  3173. if (pObj->m_pSource)
  3174. {
  3175.     theErr = pObj->m_pSource->ProcessIdle();
  3176. }
  3177. if (!theErr && 
  3178.             pObj->m_pPlayer && 
  3179.             pObj->m_pPlayer->IsInitialized() && 
  3180.             !pObj->IsInitialized())
  3181. {
  3182.     theErr = pObj->InitializeAndSetupRendererSites();
  3183. }
  3184.     }
  3185. }