srcinfo.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:99k
源码类别:

Symbian

开发平台:

C/C++

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