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

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. #if (defined( _WIN32 ) || defined( _WINDOWS )) && !defined(WIN32_PLATFORM_PSPC)
  37. #include <winsock2.h>
  38. #endif /* defined( _WIN32 ) || defined( _WINDOWS ) */
  39. #include "hxcom.h"
  40. #include "hxmime.h"
  41. #include "dbcs.h"
  42. #include "chxxtype.h"
  43. #include "hxresult.h"
  44. #ifndef _WINCE
  45. #include "hlxclib/signal.h"
  46. #endif
  47. #include "conn.h"
  48. #if defined( _WIN32 ) || defined( _WINDOWS )
  49. #include "platform/win/win_net.h"
  50. #elif defined (_MACINTOSH)
  51. #include "mac_net.h"
  52. #elif defined (_UNIX)
  53. #include "unix_net.h"
  54. #elif defined(__TCS__)
  55. #include "platform/tm1/tm1_net.h"
  56. #endif // defined( _WIN32 ) || defined( _WINDOWS )
  57. #include "hxcomm.h"
  58. #include "ihxpckts.h"
  59. #include "hxfiles.h"
  60. #include "hxformt.h"
  61. #include "hxengin.h"
  62. #include "hxcore.h"
  63. #include "hxprefs.h"
  64. #include "hxpref.h"
  65. #include "hxclsnk.h"
  66. #include "hxpends.h"
  67. #include "hxhyper.h"
  68. #include "playhpnv.h"
  69. #include "hxmon.h"
  70. #if defined(HELIX_FEATURE_ASM)
  71. #include "hxasm.h"
  72. #include "hxsmbw.h"
  73. #include "createbwman.h"
  74. #endif /* HELIX_FEATURE_ASM */
  75. #include "hxplugn.h"
  76. #include "chxeven.h"
  77. #include "chxelst.h"
  78. #include "strminfo.h"
  79. #if defined(HELIX_FEATURE_MEDIAMARKER)
  80. #include "hxmmrkr.h"
  81. #endif /* #if defined(HELIX_FEATURE_MEDIAMARKER) */
  82. #if defined(HELIX_FEATURE_EVENTMANAGER)
  83. #include "hxinter.h"
  84. #endif /* #if defined(HELIX_FEATURE_EVENTMANAGER) */
  85. #include "hxslist.h"
  86. #include "hxmap.h"
  87. #include "hxstrutl.h"
  88. //#include "plgnhand.h"
  89. #include "hxrquest.h"
  90. #include "chxelst.h"
  91. #include "hxbsrc.h"
  92. #include "hxsrc.h"
  93. #include "hxflsrc.h"
  94. #include "hxntsrc.h"
  95. #include "hxrendr.h"
  96. #include "hxwin.h"
  97. #include "hxstrm.h"
  98. #include "hxcleng.h"
  99. #include "timeline.h"
  100. #include "hxstring.h"
  101. #include "timeval.h"
  102. #include "hxerror.h"
  103. #include "sinkctl.h"
  104. #include "upgrdcol.h"
  105. #include "chxphook.h"
  106. #include "hxgroup.h"
  107. #include "basgroup.h"
  108. #include "advgroup.h"
  109. // temporary
  110. //#define DEBUG_LOG_INFO    1
  111. #include "hxstat.h"
  112. #include "auderrs.h"
  113. #include "hxausvc.h"
  114. #include "hxaudses.h"
  115. #include "hxaudply.h"
  116. #include "hxplay.h"
  117. #include "hxplugn.h"
  118. #include "hxtick.h"
  119. #include "srcinfo.h"
  120. #include "nxtgrmgr.h"
  121. #include "prefmgr.h"
  122. #include "srcinfo.h"
  123. #include "errdbg.h"
  124. #include "hxthread.h"
  125. #include "hxxrsmg.h"
  126. #include "hxresmgr.h"
  127. #include "portaddr.h"
  128. #if defined(HELIX_FEATURE_SMARTERNETWORK)
  129. #include "preftran.h"
  130. #endif /* HELIX_FEATURE_SMARTERNETWORK */
  131. #include "cookies.h"
  132. #include "viewport.h"
  133. #if defined(HELIX_FEATURE_MEDIAMARKER)
  134. #include "mediamrk.h"
  135. #endif /* #if defined(HELIX_FEATURE_MEDIAMARKER) */
  136. #if defined(HELIX_FEATURE_EVENTMANAGER)
  137. #include "eventmgr.h"
  138. #endif /* #if defined(HELIX_FEATURE_EVENTMANAGER) */
  139. #include "hxtac.h"
  140. #if defined(_STATICALLY_LINKED) || !defined(HELIX_FEATURE_PLUGINHANDLER2)
  141. #include "hxpluginmanager.h"
  142. #else
  143. #include "plghand2.h"
  144. #endif /* _STATICALLY_LINKED */
  145. //#include "../dcondev/dcon.h"
  146. //BOOL g_bRahulLog = FALSE;
  147. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  148. #include "platform/mac/hx_moreprocesses.h"
  149. #endif
  150. #ifdef _MACINTOSH
  151. #include "hxmm.h"
  152. #endif
  153. #ifdef _UNIX
  154. #include "unix_net.h"
  155. #endif
  156. #include "sitemgr.h"
  157. #include "hxheap.h"
  158. #ifdef _DEBUG
  159. #undef HX_THIS_FILE
  160. static const char HX_THIS_FILE[] = __FILE__;
  161. #endif
  162. #ifdef _WIN16
  163. extern HINSTANCE g_hInstance;       // initialized in DLLMAIN.CPP(rmacore.dll)
  164. #endif
  165. #if defined(__TCS__)
  166. #if defined(__cplusplus)
  167. extern "C" {
  168. #endif
  169. void hookRealAudio_ReportError(int err, long errVal);
  170. #ifdef __cplusplus
  171. }
  172. #endif
  173. #endif
  174. #define MIN_DELAYBEFORE_START       2000
  175. #define BEGIN_SYNC_FUDGE_FACTOR     50
  176. #define MAX_LOOP_EXE_TIME           300 //100
  177. #define ALLFS                       0xFFFFFFFF
  178. #define GOTOEXITONERROR(theErr, label)      if (theErr) goto label
  179. /* Please add any variables to be re-initialized in the ResetPlayer()
  180.  * function also.
  181.  */
  182. HXPlayer::HXPlayer() :
  183.      m_pURL (0)
  184.     ,m_lRefCount (0)
  185.     ,m_pPreferences(0)
  186.     ,m_pClientRequestSink(0)
  187.     ,m_pHyperNavigate(0)
  188.     ,m_pRegistry(0)
  189.     ,m_pStats(0)
  190.     ,m_pUpdateStatsCallback(0)
  191.     ,m_ulStatsGranularity(1000)
  192.     ,m_pEngine (0)
  193.     ,m_pPlugin2Handler(0)
  194.     ,m_pAudioPlayer (0)
  195.     ,m_uNumSourcesActive(0)
  196.     ,m_uNumCurrentSourceNotDone(0)
  197.     ,m_bInitialized (FALSE)
  198.     ,m_pPendingTrackList(NULL)
  199.     ,m_ulCurrentPlayTime (0)
  200. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  201.     ,m_ulCurrentSystemPlayTime(0)
  202. #endif
  203.     ,m_ulPresentationDuration(0)
  204.     ,m_ulTimeBeforeSeek (0)
  205.     ,m_ulTimeAfterSeek (0)
  206.     ,m_BufferingReason(BUFFERING_START_UP)
  207.     ,m_pScheduler(0)
  208.     ,m_bIsDone(TRUE)
  209.     ,m_bIsPresentationDone(TRUE)
  210.     ,m_bIsPresentationClosedToBeSent(FALSE)
  211.     ,m_bCoreLocked(FALSE)
  212.     ,m_bPaused(FALSE)
  213.     ,m_bBeginPending(FALSE)
  214.     ,m_pClient(0)
  215.     ,m_ulLowestGranularity(DEFAULT_TIMESYNC_GRANULARITY)
  216.     ,m_bTimelineToBeResumed (FALSE)
  217.     ,m_bIsPlaying(FALSE)
  218.     ,m_bNetInitialized(FALSE)
  219.     ,m_bPrefTransportInitialized(FALSE)
  220.     ,m_bIsFirstBegin(TRUE)
  221.     ,m_bIsFirstBeginPending(FALSE)
  222.     ,m_bIsLive(FALSE)
  223.     ,m_bProcessEventsLocked(FALSE)
  224.     ,m_bTimeSyncLocked(FALSE)
  225.     ,m_bCurrentPresentationClosed(FALSE)
  226.     ,m_LastError(HXR_OK)
  227.     ,m_bInStop(FALSE)
  228.     ,m_bPlayerWithoutSources(FALSE)
  229.     ,m_ulMinimumAudioPreroll(0)
  230.     ,m_ulMinimumTotalPreroll(0)
  231.     ,m_bInternalPauseResume(FALSE)
  232.     ,m_bInternalReset(FALSE)
  233.     ,m_pErrorSinkControl(NULL)
  234.     ,m_pAdviseSink(NULL)
  235.     ,m_pSiteManager(NULL)
  236.     ,m_pSiteSupplier(NULL)
  237.     ,m_pHXPlayerCallback(0)
  238.     ,m_pSetupCallback(0)
  239.     ,m_pAuthenticationCallback(NULL)
  240.     ,m_pHXPlayerInterruptCallback(NULL)
  241.     ,m_nGroupCount(0)
  242.     ,m_nCurrentGroup(0)
  243.     ,m_bContactingDone(FALSE)
  244.     ,m_pUpgradeCollection(NULL)
  245.     ,m_pPacketHookManager(NULL)
  246.     ,m_bIsFirstTimeSync(TRUE)
  247.     ,m_ulFirstTimeSync(0)
  248.     ,m_ulElapsedPauseTime(0)
  249.     ,m_ulLiveSeekTime(0)
  250.     ,m_ulTimeOfPause(0)
  251.     ,m_bLiveSeekToBeDone(FALSE)
  252.     ,m_bFastStartInProgress(FALSE)
  253.     ,m_ulFSBufferingEndTime(0)
  254.     ,m_bAllLocalSources(TRUE)
  255.     ,m_bFSBufferingEnd(FALSE)
  256.     ,m_pGroupManager(NULL)
  257.     ,m_bPartOfNextGroup(FALSE)
  258.     ,m_pNextGroupManager(NULL)
  259.     ,m_pPrefetchManager(NULL)
  260.     ,m_bLastGroup(FALSE)
  261.     ,m_bNextGroupStarted(FALSE)
  262.     ,m_bDidWeDeleteAllEvents(FALSE)
  263.     ,m_bSetupLayoutSiteGroup(TRUE)
  264.     ,m_pCurrentGroup(NULL)
  265.     ,m_bBeginChangeLayoutTobeCalled(TRUE)
  266.     ,m_b100BufferingToBeSent(TRUE)
  267.     ,m_bUserHasCalledBegin(FALSE)
  268.     ,m_bCloseAllRenderersPending(FALSE)
  269.     ,m_uNumSourceToBeInitializedBeforeBegin(0)
  270.     ,m_pCoreMutex(NULL)
  271.     ,m_bSetupToBeDone(FALSE)
  272.     ,m_bPostSetupToBeDone(FALSE)
  273.     ,m_pRequest(NULL)
  274.     ,m_pAltURLs(NULL)
  275.     ,m_bActiveRequest(FALSE)
  276.     ,m_bUseCoreThread(FALSE)
  277.     ,m_bAddLayoutSiteGroupCalled(FALSE)
  278.     ,m_pLastUserString(NULL)
  279.     ,m_pLastMoreInfoURL(NULL)
  280.     ,m_bForceStatsUpdate(FALSE)
  281. #if defined(HELIX_FEATURE_ASM)
  282.     ,m_pBandwidthMgr(NULL)
  283.     ,m_pASM(NULL)
  284. #endif
  285.     ,m_pRedirectList(NULL)
  286.     ,m_bPendingAudioPause(FALSE) // currently used ONLY on Mac
  287.     ,m_bPlayStateNotified(FALSE)
  288.     ,m_bResumeOnlyAtSystemTime(FALSE)
  289.     ,m_bSourceMapUpdated(FALSE)
  290.     ,m_pPreferredTransportManager(NULL)
  291.     ,m_pNetInterfaces(NULL)
  292.     ,m_pClientViewSource(NULL)
  293.     ,m_pViewPortManager(NULL)
  294.     ,m_pMediaMarkerManager(NULL)
  295.     ,m_pEventManager(NULL)
  296.     ,m_pClientViewRights(NULL)
  297.     ,m_ulRepeatedRegistryID(0)
  298.     ,m_ulNextGroupRegistryID(0)
  299.     ,m_pCookies(NULL)
  300.     ,m_pParentPlayer(NULL)
  301.     ,m_pChildPlayerList(NULL)
  302.     ,m_bSetModal(FALSE)
  303.     ,m_pPersistentComponentManager(NULL)
  304.     ,m_pAutheticationValues(NULL)
  305.     ,m_bDoRedirect(FALSE)
  306.     ,m_ulActiveSureStreamSource(0)
  307.     ,m_bFastStartCheckDone(FALSE)
  308.     ,m_bFastStart(FALSE)
  309.     ,m_turboPlayOffReason(TP_OFF_BY_UNKNOWN)
  310.     ,m_pMasterTAC(NULL)
  311. #ifdef _WIN32
  312.     ,m_bScreenSaverActive(0)
  313. #endif
  314.     ,m_pRecordService(NULL)
  315.     ,m_bRecordServiceEnabled(FALSE)
  316. /* Please add any variables to be re-initialized in the ResetPlayer()
  317.  * function also.
  318.  */
  319. {
  320.     m_pSourceMap = new CHXMapPtrToPtr;
  321.     m_pSharedWallClocks = new CHXMapStringToOb;
  322.     
  323. #if defined(_DEBUG) && defined(DEBUG_LOG_INFO)
  324.          HXStaticStatLog::Open_Write("e:\log.txt");
  325. #endif // DEBUG_LOG_INFO
  326.     ResetError();
  327. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  328.     m_pUpdateStatsCallback              = new UpdateStatsCallback;
  329.     m_pUpdateStatsCallback->m_pPlayer   = this;
  330.     m_pUpdateStatsCallback->AddRef();
  331. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  332. #if defined (_WIN32) || defined (_MACINTOSH) || defined(THREADS_SUPPORTED)
  333.     m_pHXPlayerCallback = new HXPlayerCallback((void*)this, (fGenericCBFunc)PlayerCallback);
  334.     m_pHXPlayerInterruptCallback = new HXPlayerCallback((void*)this, (fGenericCBFunc)PlayerCallback);
  335.     m_pSetupCallback = new HXPlayerCallback((void*)this, (fGenericCBFunc)SetupCallback);
  336.     ((HXPlayerCallback*)m_pHXPlayerInterruptCallback)->m_bInterrupSafe  = TRUE;
  337.     ((HXPlayerCallback*)m_pSetupCallback)->m_bInterrupSafe = TRUE;
  338. #else
  339.     m_pHXPlayerCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)PlayerCallback);
  340.     m_pHXPlayerInterruptCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)PlayerCallback);
  341.     m_pSetupCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)SetupCallback);
  342. #endif
  343.     m_pHXPlayerCallback->AddRef();
  344.     m_pHXPlayerInterruptCallback->AddRef();
  345.     m_pSetupCallback->AddRef();
  346. #if defined(HELIX_FEATURE_AUTHENTICATION)
  347.     m_pAuthenticationCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)AuthenticationCallback);
  348.     m_pAuthenticationCallback->AddRef();
  349. #endif /* HELIX_FEATURE_AUTHENTICATION */
  350. #if defined(HELIX_FEATURE_SINKCONTROL)
  351.     m_pErrorSinkControl     = new CHXErrorSinkControl;
  352.     m_pAdviseSink           = new CHXAdviseSinkControl;
  353. #endif /* HELIX_FEATURE_SINKCONTROL */
  354. #if defined(HELIX_FEATURE_VIDEO)
  355.     m_pSiteManager          = new CHXSiteManager();
  356. #endif /* HELIX_FEATURE_VIDEO */
  357. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR)
  358.     m_pGroupManager         = new HXAdvancedGroupManager(this);
  359. #elif defined(HELIX_FEATURE_BASICGROUPMGR)
  360.     m_pGroupManager         = new HXBasicGroupManager(this);
  361. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR */
  362. #if defined(HELIX_FEATURE_NEXTGROUPMGR)
  363.     m_pNextGroupManager     = new NextGroupManager(this);
  364. #endif /* HELIX_FEATURE_NEXTGROUPMGR */
  365. #if defined(HELIX_FEATURE_MASTERTAC)
  366.     m_pMasterTAC            = new HXMasterTAC(m_pGroupManager);
  367. #endif /* HELIX_FEATURE_MASTERTAC */
  368. #if defined(HELIX_FEATURE_VIEWPORT)
  369.     m_pViewPortManager      = new HXViewPortManager(this);
  370. #endif /* HELIX_FEATURE_VIEWPORT */
  371. #if defined(HELIX_FEATURE_MEDIAMARKER)
  372.     m_pMediaMarkerManager   = new CHXMediaMarkerManager(this);
  373.     if (m_pMediaMarkerManager) m_pMediaMarkerManager->AddRef();
  374. #endif /* #if defined(HELIX_FEATURE_MEDIAMARKER) */
  375. #if defined(HELIX_FEATURE_NESTEDMETA)
  376.     m_pPersistentComponentManager = new HXPersistentComponentManager(this);
  377. #endif /* HELIX_FEATURE_NESTEDMETA */
  378.     HX_ADDREF(m_pErrorSinkControl);
  379.     HX_ADDREF(m_pAdviseSink);
  380. #if defined(HELIX_FEATURE_VIDEO)
  381.     m_pSiteManager->AddRef();
  382. #endif /* HELIX_FEATURE_VIDEO */
  383. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  384.     m_pGroupManager->AddRef();
  385.     m_pGroupManager->AddSink(this);
  386. #endif /* HELIX_FEATURE_BASICGROUPMGR */
  387.     HX_ADDREF(m_pMasterTAC);
  388. #if defined(HELIX_FEATURE_VIEWPORT)
  389.     m_pViewPortManager->AddRef();
  390. #endif /* HELIX_FEATURE_VIEWPORT */
  391. #if defined(HELIX_FEATURE_ADVANCEDGROUPMGR) && defined(HELIX_FEATURE_MASTERTAC)
  392.     if (m_pGroupManager && m_pMasterTAC)
  393.     {
  394.         m_pGroupManager->SetMasterTAC(m_pMasterTAC);
  395.     }
  396. #endif /* HELIX_FEATURE_ADVANCEDGROUPMGR && HELIX_FEATURE_MASTERTAC */
  397. #if defined(HELIX_FEATURE_NESTEDMETA)
  398.     m_pPersistentComponentManager->AddRef();
  399.     if (m_pGroupManager)
  400.     {
  401.         m_pGroupManager->AddSink(m_pPersistentComponentManager);
  402.     }
  403. #endif /* HELIX_FEATURE_NESTEDMETA */
  404. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  405.     m_pUpgradeCollection = new HXUpgradeCollection;
  406.     m_pUpgradeCollection->AddRef();
  407. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  408. #if defined(HELIX_FEATURE_EVENTMANAGER)
  409.     // Get our own IUnknown interface
  410.     IUnknown* pUnknown = NULL;
  411.     QueryInterface(IID_IUnknown, (void**) &pUnknown);
  412.     if (pUnknown)
  413.     {
  414.         // Initialize the renderer event manager
  415.         m_pEventManager = new CRendererEventManager(pUnknown);
  416.         if (m_pEventManager) m_pEventManager->AddRef();
  417.     }
  418.     HX_RELEASE(pUnknown);
  419. #endif /* #if defined(HELIX_FEATURE_EVENTMANAGER) */
  420. }
  421. HXPlayer::~HXPlayer()
  422. {
  423.     CloseAllRenderers(m_nCurrentGroup);
  424.     ResetPlayer();
  425.     Close();
  426.     HX_DELETE(m_pSourceMap);
  427.     HX_DELETE(m_pSharedWallClocks);
  428. }
  429. /////////////////////////////////////////////////////////////////////////
  430. //      Method:
  431. //              IUnknown::QueryInterface
  432. //      Purpose:
  433. //              Implement this to export the interfaces supported by your
  434. //              object.
  435. //
  436. STDMETHODIMP HXPlayer::QueryInterface(REFIID riid, void** ppvObj)
  437. {
  438. #if defined(HELIX_FEATURE_PACKETHOOKMGR)
  439.     // create the following objects only if needed
  440.     if (!m_pPacketHookManager && IsEqualIID(riid, IID_IHXPacketHookManager))
  441.     {
  442.         m_pPacketHookManager = new PacketHookManager(this);
  443.         if (m_pPacketHookManager)
  444.         {
  445.             m_pPacketHookManager->AddRef();
  446.         }
  447.     }
  448. #endif /* HELIX_FEATURE_PACKETHOOKMGR */
  449.     QInterfaceList qiList[] =
  450.         {
  451.             { GET_IIDHANDLE(IID_IHXPlayer), (IHXPlayer*)this },
  452.             { GET_IIDHANDLE(IID_IHXPlayer2), (IHXPlayer2*)this },
  453.             { GET_IIDHANDLE(IID_IHXPendingStatus), (IHXPendingStatus*)this },
  454. #if defined(HELIX_FEATURE_AUTHENTICATION)
  455.             { GET_IIDHANDLE(IID_IHXAuthenticationManager), (IHXAuthenticationManager*)this },
  456.             { GET_IIDHANDLE(IID_IHXAuthenticationManager2), (IHXAuthenticationManager2*)this },
  457. #endif /* HELIX_FEATURE_AUTHENTICATION */
  458.             { GET_IIDHANDLE(IID_IHXGroupSink), (IHXGroupSink*)this },
  459.             { GET_IIDHANDLE(IID_IHXAudioPlayerResponse), (IHXAudioPlayerResponse*)this },
  460.             { GET_IIDHANDLE(IID_IHXRegistryID), (IHXRegistryID*)this },
  461.             { GET_IIDHANDLE(IID_IHXErrorMessages), (IHXErrorMessages*)this },
  462.             { GET_IIDHANDLE(IID_IHXLayoutSiteGroupManager), (IHXLayoutSiteGroupManager*)this },
  463. #if defined(HELIX_FEATURE_NESTEDMETA)
  464.             { GET_IIDHANDLE(IID_IHXPersistenceManager), (IHXPersistenceManager*)this },
  465. #endif /* HELIX_FEATURE_NESTEDMETA */
  466.             { GET_IIDHANDLE(IID_IHXDriverStreamManager), (IHXDriverStreamManager*)this },
  467.             { GET_IIDHANDLE(IID_IHXRendererUpgrade), (IHXRendererUpgrade*)this },
  468.             { GET_IIDHANDLE(IID_IHXInternalReset), (IHXInternalReset*)this },
  469.             { GET_IIDHANDLE(IID_IHXPlayerState), (IHXPlayerState*)this },
  470. #if defined(HELIX_FEATURE_PLAYERNAVIGATOR)
  471.             { GET_IIDHANDLE(IID_IHXPlayerNavigator), (IHXPlayerNavigator*)this },
  472. #endif /* HELIX_FEATURE_PLAYERNAVIGATOR */
  473.             { GET_IIDHANDLE(IID_IHXClientStatisticsGranularity), (IHXClientStatisticsGranularity*)this },
  474.             { GET_IIDHANDLE(IID_IHXPlayerPresentation), (IHXPlayerPresentation*)this },
  475. #if defined(HELIX_FEATURE_RECORDCONTROL)
  476.             { GET_IIDHANDLE(IID_IHXRecordManager), (IHXRecordManager*)this },
  477. #endif /* HELIX_FEATURE_RECORDCONTROL */
  478.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXPlayer*)this },
  479.             { GET_IIDHANDLE(IID_IHXOverrideDefaultServices), (IHXOverrideDefaultServices*)this },
  480.         };
  481.     HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  482.     
  483.     // if it succeeded, return immediately...
  484.     if (res == HXR_OK)
  485.     {
  486.         return res;
  487.     }
  488.     // ...otherwise continue onward
  489.     
  490.     if (m_pClientViewSource &&
  491.              IsEqualIID(riid, IID_IHXViewSourceCommand))
  492.     {
  493.         AddRef();
  494.         *ppvObj = (IHXViewSourceCommand*)this;
  495.         return HXR_OK;
  496.     }
  497.     else if (m_pErrorSinkControl &&
  498.              m_pErrorSinkControl->QueryInterface(riid, ppvObj) == HXR_OK)
  499.     {
  500.         return HXR_OK;
  501.     }
  502.     else if (m_pAdviseSink &&
  503.              m_pAdviseSink->QueryInterface(riid, ppvObj) == HXR_OK)
  504.     {
  505.         return HXR_OK;
  506.     }
  507.     else if (m_pAudioPlayer &&
  508.              m_pAudioPlayer->QueryInterface(riid, ppvObj) == HXR_OK)
  509.     {
  510.         return HXR_OK;
  511.     }
  512. #if defined(HELIX_FEATURE_PREFERENCES)
  513.     else if (m_pPreferences &&
  514.              m_pPreferences->QueryInterface(riid, ppvObj) == HXR_OK)
  515.     {
  516.         return HXR_OK;
  517.     }
  518. #endif /* HELIX_FEATURE_PREFERENCES */
  519. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  520.     else if (m_pHyperNavigate &&
  521.              m_pHyperNavigate->QueryInterface(riid, ppvObj) == HXR_OK)
  522.     {
  523.         return HXR_OK;
  524.     }
  525. #endif /* HELIX_FEATURE_HYPER_NAVIGATE */
  526. #if defined(HELIX_FEATURE_ASM)
  527.     /* m_pASM will be available on a per player basis ONLY under Load testing */
  528.     else if (m_pASM &&
  529.              m_pASM->QueryInterface(riid, ppvObj) == HXR_OK)
  530.     {
  531.         return HXR_OK;
  532.     }
  533. #endif /* HELIX_FEATURE_ASM */
  534. #if defined(HELIX_FEATURE_VIDEO)
  535.     else if (m_pSiteManager &&
  536.              m_pSiteManager->QueryInterface(riid, ppvObj) == HXR_OK)
  537.     {
  538.         return HXR_OK;
  539.     }
  540. #endif /* HELIX_FEATURE_VIDEO */
  541. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  542.     else if (m_pUpgradeCollection &&
  543.              m_pUpgradeCollection->QueryInterface(riid, ppvObj) == HXR_OK)
  544.     {
  545.         return HXR_OK;
  546.     }
  547. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  548. #if defined(HELIX_FEATURE_PACKETHOOKMGR)
  549.     else if (m_pPacketHookManager &&
  550.              m_pPacketHookManager->QueryInterface(riid, ppvObj) == HXR_OK)
  551.     {
  552.         return HXR_OK;
  553.     }
  554. #endif /* HELIX_FEATURE_PACKETHOOKMGR */
  555. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  556.     else if (m_pGroupManager &&
  557.              m_pGroupManager->QueryInterface(riid, ppvObj) == HXR_OK)
  558.     {
  559.         return HXR_OK;
  560.     }
  561. #endif /* HELIX_FEATURE_BASICGROUPMGR */
  562.     else if (m_pViewPortManager &&
  563.              m_pViewPortManager->QueryInterface(riid, ppvObj) == HXR_OK)
  564.     {
  565.         return HXR_OK;
  566.     }
  567. #if defined(HELIX_FEATURE_MEDIAMARKER)
  568.     else if (m_pMediaMarkerManager &&
  569.              m_pMediaMarkerManager->QueryInterface(riid, ppvObj) == HXR_OK)
  570.     {
  571.         return HXR_OK;
  572.     }
  573. #endif /* #if defined(HELIX_FEATURE_MEDIAMARKER) */
  574. #if defined(HELIX_FEATURE_EVENTMANAGER)
  575.     else if (m_pEventManager &&
  576.              m_pEventManager->QueryInterface(riid, ppvObj) == HXR_OK)
  577.     {
  578.         return HXR_OK;
  579.     }
  580. #endif /* #if defined(HELIX_FEATURE_EVENTMANAGER) */
  581. #if defined(HELIX_FEATURE_NESTEDMETA)
  582.     else if (m_pPersistentComponentManager &&
  583.              m_pPersistentComponentManager->QueryInterface(riid, ppvObj) == HXR_OK)
  584.     {
  585.         return HXR_OK;
  586.     }
  587. #endif /* HELIX_FEATURE_NESTEDMETA */
  588.     else if (m_pPlugin2Handler &&
  589.              m_pPlugin2Handler->QueryInterface(riid, ppvObj) == HXR_OK)
  590.     {
  591.         return HXR_OK;
  592.     }
  593.     else if (m_pClient &&
  594.              m_pClient->QueryInterface(riid, ppvObj) == HXR_OK)
  595.     {
  596.         return HXR_OK;
  597.     }
  598.     else if (m_pEngine &&
  599.              m_pEngine->QueryInterface(riid, ppvObj) == HXR_OK)
  600.     {
  601.         return HXR_OK;
  602.     }
  603.     /* DO NOT ADD ANY MROE QIs HERE. ADD IT BEFORE m_pClient QI*/
  604.     *ppvObj = NULL;
  605.     return HXR_NOINTERFACE;
  606. }
  607. /////////////////////////////////////////////////////////////////////////
  608. //      Method:
  609. //              IUnknown::AddRef
  610. //      Purpose:
  611. //              Everyone usually implements this the same... feel free to use
  612. //              this implementation.
  613. //
  614. STDMETHODIMP_(ULONG32) HXPlayer::AddRef()
  615. {
  616.     return InterlockedIncrement(&m_lRefCount);
  617. }
  618. /////////////////////////////////////////////////////////////////////////
  619. //      Method:
  620. //              IUnknown::Release
  621. //      Purpose:
  622. //              Everyone usually implements this the same... feel free to use
  623. //              this implementation.
  624. //
  625. STDMETHODIMP_(ULONG32) HXPlayer::Release()
  626. {
  627.     if (InterlockedDecrement(&m_lRefCount) > 0)
  628.     {
  629.         return m_lRefCount;
  630.     }
  631.     if(m_lRefCount == 0)
  632.     {
  633.         delete this;
  634.     }
  635.     return 0;
  636. }
  637. // *** IHXPlayer methods ***
  638. /************************************************************************
  639.  *      Method:
  640.  *              IHXPlayer::GetClientEngine
  641.  *      Purpose:
  642.  *              Get the interface to the client engine object of which the player
  643.  *              is a part of.
  644.  *
  645.  */
  646. STDMETHODIMP HXPlayer::GetClientEngine(IHXClientEngine* &pEngine)
  647. {
  648.     pEngine = m_pEngine;
  649.     if (pEngine)
  650.     {
  651.         pEngine->AddRef();
  652.     }
  653.     return HXR_OK;
  654. }
  655. /************************************************************************
  656.  *      Method:
  657.  *              IHXPlayer::Begin
  658.  *      Purpose:
  659.  *              Tell the player to begin playback of all its sources.
  660.  *
  661.  */
  662. STDMETHODIMP HXPlayer::Begin(void)
  663. {
  664.     HX_RESULT theErr = HXR_OK;
  665.     m_bCoreLocked = TRUE;
  666.     m_pCoreMutex->Lock();
  667.     theErr = BeginPlayer();
  668.     m_pCoreMutex->Unlock();
  669.     m_bCoreLocked = FALSE;
  670.     return theErr;
  671. }
  672. HX_RESULT
  673. HXPlayer::BeginPlayer(void)
  674. {
  675.     HX_RESULT   theErr = HXR_OK;
  676.     m_bUserHasCalledBegin   = TRUE;
  677.     m_bFastStartInProgress  = FALSE;
  678.     if (!m_bInternalPauseResume && !m_bIsFirstBegin && !m_bPaused)
  679.     {
  680.         return HXR_OK;
  681.     }
  682.     if (m_bIsLive && m_bPaused && m_bLiveSeekToBeDone)
  683.     {
  684.         m_ulElapsedPauseTime = CALCULATE_ELAPSED_TICKS(m_ulTimeOfPause, HX_GET_TICKCOUNT());
  685.         /* This is an internal seek due to live pause */
  686.         theErr = SeekPlayer(m_ulLiveSeekTime + m_ulElapsedPauseTime);
  687.     }
  688.     m_bPaused = FALSE;
  689.     if (m_bIsFirstBegin)
  690.     {
  691.         UpdateSourceActive();
  692.     }
  693.     if (!theErr)
  694.     {
  695.         theErr = UpdateStatistics();
  696.     }
  697.     if (!theErr)
  698.     {
  699.         UpdateCurrentPlayTime( m_pAudioPlayer->GetCurrentPlayBackTime() );
  700.     }
  701.     /* Unregister all the sources that are not currently active */
  702.     UnregisterNonActiveSources();
  703.     if (!m_bIsDone)
  704.     {
  705.         CheckSourceRegistration();
  706.         CHXMapPtrToPtr::Iterator ndxSources = m_pSourceMap->Begin();
  707.         /* Check if we are done. This may be TRUE for empty files */
  708.         for (;  !theErr && ndxSources != m_pSourceMap->End(); ++ndxSources)
  709.         {
  710.             SourceInfo* pSourceInfo = (SourceInfo*) (*ndxSources);
  711.             theErr = pSourceInfo->Begin();
  712.         }
  713.     }
  714.     /* Only send this OnBegin()'s if not the first begin. In the case
  715.      * of the first begin, these are actually sent after the header's
  716.      * arrive...
  717.      */
  718.     if (!theErr && !m_bIsFirstBegin && !m_bInternalPauseResume && !m_bInternalReset && m_pAdviseSink)
  719.     {
  720.         m_pAdviseSink->OnBegin(m_ulCurrentPlayTime);
  721.     }
  722.     m_bIsFirstBegin = FALSE;
  723.     m_bBeginPending = TRUE;
  724.     m_bFastStartInProgress  = FALSE;
  725.     if (!m_ToBeginRendererList.IsEmpty())
  726.     {
  727.         CheckBeginList();
  728.     }
  729.     return (theErr);
  730. }
  731. /************************************************************************
  732.  *      Method:
  733.  *              IHXPlayer::Stop
  734.  *      Purpose:
  735.  *              Tell the player to stop playback of all its sources.
  736.  *
  737.  */
  738. STDMETHODIMP HXPlayer::Stop(void)
  739. {
  740.     // we want to protect against the TLC opening another URL
  741.     if (m_bSetModal)
  742.     {
  743.         return HXR_OK;
  744.     }
  745.     m_bCoreLocked = TRUE;
  746.     m_pCoreMutex->Lock();
  747.     StopPlayer(END_STOP);
  748.     m_pCoreMutex->Unlock();
  749.     m_bCoreLocked = FALSE;
  750.     return HXR_OK;
  751. }
  752. void
  753. HXPlayer::StopPlayer(EndCode endCode)
  754. {
  755.     StopAllStreams(endCode);
  756.     /* Reset player condition */
  757.     ResetPlayer();
  758. }
  759. /************************************************************************
  760.  *      Method:
  761.  *              IHXPlayer::Pause
  762.  *      Purpose:
  763.  *              Tell the player to pause playback of all its sources.
  764.  *
  765.  */
  766. STDMETHODIMP HXPlayer::Pause(void)
  767. {
  768.     HX_RESULT theErr = HXR_OK;
  769.     m_bCoreLocked = TRUE;
  770.     m_pCoreMutex->Lock();
  771.     theErr = PausePlayer();
  772.     m_pCoreMutex->Unlock();
  773.     m_bCoreLocked = FALSE;
  774.     return theErr;
  775. }
  776. HX_RESULT
  777. HXPlayer::PausePlayer(BOOL bNotifyTLC /* = TRUE*/)
  778. {
  779.     HX_RESULT theErr = HXR_OK;
  780.     if (m_bIsDone)
  781.     {
  782.         return HXR_UNEXPECTED;
  783.     }
  784.     if (m_bPaused)
  785.     {
  786.         return HXR_OK;
  787.     }
  788.     m_bPaused = TRUE;
  789.     if (m_bIsLive && !(m_bRecordServiceEnabled && m_pRecordService))
  790.     {
  791.         m_bLiveSeekToBeDone = TRUE;
  792.         m_ulLiveSeekTime    = m_pAudioPlayer->GetCurrentPlayBackTime();
  793.         m_ulTimeOfPause     = HX_GET_TICKCOUNT();
  794.     }
  795.     m_bIsPlaying            = FALSE;
  796.     m_bTimelineToBeResumed  = TRUE;
  797.     m_pAudioPlayer->Pause();
  798.     CHXMapPtrToPtr::Iterator ndxSource = m_pSourceMap->Begin();
  799.     for (;  !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  800.     {
  801.         SourceInfo* pSourceInfo = (SourceInfo*)(*ndxSource);
  802.         theErr = pSourceInfo->Pause();
  803.     }
  804.     /* Send OnPause to advice sink ONLY if it is not an internal Pause */
  805.     if (bNotifyTLC && !m_bInternalPauseResume && !m_bInternalReset && m_pAdviseSink)
  806.     {
  807.         m_pAdviseSink->OnPause(m_ulCurrentPlayTime);
  808.     }
  809.     return (theErr);
  810. }
  811. /************************************************************************
  812.  *      Method:
  813.  *              IHXPlayer::Seek
  814.  *      Purpose:
  815.  *              Tell the player to seek in the playback timeline of all its
  816.  *              sources.
  817.  *
  818.  */
  819. STDMETHODIMP HXPlayer::Seek(ULONG32    ulTime)
  820. {
  821.     HX_RESULT theErr = HXR_OK;
  822.     m_bCoreLocked = TRUE;
  823.     m_pCoreMutex->Lock();
  824.     theErr = SeekPlayer(ulTime);
  825.     m_pCoreMutex->Unlock();
  826.     m_bCoreLocked = FALSE;
  827.     return theErr;
  828. }
  829. HX_RESULT
  830. HXPlayer::SeekPlayer(ULONG32    ulTime)
  831. {
  832.     HX_RESULT theErr = HXR_OK;
  833.     if (m_bIsDone)
  834.     {
  835.         return HXR_UNEXPECTED;
  836.     }
  837.     // do not allow seeking till we have been initialized
  838.     if (!m_bInitialized)
  839.     {
  840.         return HXR_NOT_INITIALIZED;
  841.     }
  842.     /* we do allow internal seek (done during resume after live pause)*/
  843.     if ((m_bIsLive && !m_bLiveSeekToBeDone && !(m_bRecordServiceEnabled && m_pRecordService)) ||
  844.         !AreAllSourcesSeekable())
  845.     {
  846.         /* Add error code for HXR_OPERATION_NOT_ALLOWED*/
  847.         return HXR_FAILED;
  848.     }
  849.     /* Someone called Seek without calling Pause, So we will have to call
  850.      * Pause and Resume internally
  851.      */
  852.     if (!m_bPaused)
  853.     {
  854.         m_bInternalPauseResume  = TRUE;
  855.         PausePlayer();
  856.     }
  857. #if defined(HELIX_FEATURE_NEXTGROUPMGR)
  858.     /* Stop prefetching */
  859.     if (m_pNextGroupManager->GetNumSources() > 0)
  860.     {
  861.         m_pNextGroupManager->StopPreFetch();
  862.         m_bLastGroup        = FALSE;
  863.         m_bNextGroupStarted = FALSE;
  864.     }
  865. #endif /* HELIX_FEATURE_NEXTGROUPMGR */
  866.     m_ulTimeBeforeSeek  = m_pAudioPlayer->GetCurrentPlayBackTime();
  867.     m_ulTimeAfterSeek   = ulTime;
  868.     UpdateCurrentPlayTime(ulTime);
  869.     m_pAudioPlayer->Seek(ulTime);
  870.     CHXMapPtrToPtr::Iterator ndxSource = m_pSourceMap->Begin();
  871.     for (; !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  872.     {
  873.         SourceInfo* pSourceInfo = (SourceInfo*)(*ndxSource);
  874.         pSourceInfo->Seek(ulTime);
  875.     }
  876.     if (m_pAdviseSink)
  877.     {
  878.         m_pAdviseSink->OnPreSeek(m_ulTimeBeforeSeek, m_ulTimeAfterSeek);
  879.     }
  880.     // change the state of buffering to seek
  881.     if (m_bIsLive)
  882.     {
  883.         m_BufferingReason       = BUFFERING_LIVE_PAUSE;
  884.     }
  885.     else
  886.     {
  887.         m_BufferingReason       = BUFFERING_SEEK;
  888.     }
  889.     /* Send all pre-seek events to the renderers */
  890.     SendPreSeekEvents();
  891.     ndxSource = m_pSourceMap->Begin();
  892.     for (; !theErr && ndxSource != m_pSourceMap->End();)
  893.     {
  894.         SourceInfo* pSourceInfo = (SourceInfo*)(*ndxSource);
  895.         HXSource * pSource = pSourceInfo->m_pSource;
  896.         // since the map index could be screwed up by the removing of
  897.         // the current node in AdjustSeekOnRepeatedSource()
  898.         ++ndxSource;
  899.         /* pSource should never be NULL */
  900.         HX_ASSERT(pSource);
  901.         if (pSourceInfo->m_bSeekPending || !pSourceInfo->IsInitialized())
  902.         {
  903.             continue;
  904.         }
  905.         /* This will pump all pre-seek packets to the renderer(s) */
  906.         if (pSourceInfo->m_pPeerSourceInfo)
  907.         {
  908.             theErr = AdjustSeekOnRepeatedSource(pSourceInfo, ulTime);
  909.         }
  910.         else
  911.         {
  912.             theErr = pSource->DoSeek(ulTime);
  913.         }
  914.     }
  915.     m_b100BufferingToBeSent = TRUE;
  916.     // reset the player state
  917.     UpdateSourceActive();
  918.     m_bIsDone           = FALSE;
  919.     if (!theErr)
  920.     {
  921.         if (m_bInternalPauseResume)
  922.         {
  923.             theErr = Begin();
  924.             m_bInternalPauseResume = FALSE;
  925.         }
  926.         else
  927.         {
  928.             /* Start pre-fetch */
  929.             theErr = StartDownload();
  930.         }
  931.     }
  932.     return (theErr);
  933. }
  934. /************************************************************************
  935.  *  Method:
  936.  *    IHXPlayer::GetSourceCount
  937.  *  Purpose:
  938.  *    Returns the current number of source instances supported by
  939.  *    this player instance.
  940.  */
  941. STDMETHODIMP_(UINT16) HXPlayer::GetSourceCount()
  942. {
  943.     /* We may have stopped the sources but not removed from the SourceMap
  944.      * since we need to keep the renderers active till the next URL is
  945.      * opened. In this case, report the current number of active sources
  946.      * as zero.
  947.      */
  948.     if (m_bCloseAllRenderersPending)
  949.     {
  950.         return 0;
  951.     }
  952.     else
  953.     {
  954.         return (UINT16)m_pSourceMap->GetCount();
  955.     }
  956. }
  957. /************************************************************************
  958.  *  Method:
  959.  *    IHXPlayer::GetSource
  960.  *  Purpose:
  961.  *    Returns the Nth source instance supported by this player.
  962.  */
  963. STDMETHODIMP HXPlayer::GetSource
  964. (
  965.     UINT16              nIndex,
  966.     REF(IUnknown*)      pUnknown
  967. )
  968. {
  969.     pUnknown = NULL;
  970.     if (m_bCloseAllRenderersPending || nIndex >= m_pSourceMap->GetCount())
  971.     {
  972.         return HXR_INVALID_PARAMETER;
  973.     }
  974.     CHXMapPtrToPtr::Iterator ndxSource = m_pSourceMap->Begin();
  975.     for (UINT16 i = 0; i < nIndex; i++)
  976.     {
  977.         ++ndxSource;
  978.     }
  979.     SourceInfo* pSourceInfo = (SourceInfo*)(*ndxSource);
  980.     HX_ASSERT(pSourceInfo);
  981.     HXSource* pSource = pSourceInfo->m_pSource;
  982.     if(!pSource)
  983.     {
  984.         pUnknown = NULL;
  985.         return HXR_UNEXPECTED;
  986.     }
  987.     return pSource ? pSource->QueryInterface(IID_IUnknown,(void**)&pUnknown) : HXR_FAIL;
  988. }
  989. /************************************************************************
  990.  *  Method:
  991.  *    IHXPlayer::GetClientContext
  992.  *  Purpose:
  993.  *    Called by the get the client context for this player. This is
  994.  *    traditionally to determine called by top level client application.
  995.  */
  996. STDMETHODIMP HXPlayer::GetClientContext
  997. (
  998.     REF(IUnknown*)      pUnknown
  999. )
  1000. {
  1001.     pUnknown = m_pClient;
  1002.     if (m_pClient)
  1003.     {
  1004.         m_pClient->AddRef();
  1005.     }
  1006.     return HXR_OK;
  1007. }
  1008. /************************************************************************
  1009.  *  Method:
  1010.  *      IHXPlayer::SetClientContext
  1011.  *  Purpose:
  1012.  *      Called by the client to install itself as the provider of client
  1013.  *      services to the core. This is traditionally called by the top
  1014.  *      level client application.
  1015.  */
  1016. STDMETHODIMP HXPlayer::SetClientContext(IUnknown* pUnknown)
  1017. {
  1018.     if (m_pClient) return HXR_UNEXPECTED;
  1019.     if (!pUnknown) return HXR_UNEXPECTED;
  1020.     m_pClient = pUnknown;
  1021.     m_pClient->AddRef();
  1022.     /* Override Default objects */
  1023. #if defined(HELIX_FEATURE_PREFERENCES)
  1024.     IHXPreferences* pPreferences = 0;
  1025.     if (HXR_OK == m_pClient->QueryInterface(IID_IHXPreferences, (void**) &pPreferences) ||
  1026.         HXR_OK == m_pEngine->QueryInterface(IID_IHXPreferences, (void**) &pPreferences))
  1027.     {
  1028.         HX_RELEASE(m_pPreferences);
  1029.         m_pPreferences = pPreferences;
  1030.     }
  1031. #endif /* HELIX_FEATURE_PREFERENCES */
  1032. #if defined(HELIX_FEATURE_HYPER_NAVIGATE)
  1033.     IHXHyperNavigate* pHyperNavigate = NULL;
  1034.     IHXHyperNavigateWithContext* pHyperNavigateWithContext = NULL;
  1035.     m_pClient->QueryInterface(IID_IHXHyperNavigateWithContext,
  1036.                                 (void**) &pHyperNavigateWithContext);
  1037.     m_pClient->QueryInterface(IID_IHXHyperNavigate, (void**) &pHyperNavigate);
  1038.     if (pHyperNavigate == NULL)
  1039.     {
  1040.         m_pEngine->QueryInterface(IID_IHXHyperNavigate, (void**) &pHyperNavigate);
  1041.     }
  1042.     HX_ASSERT(pHyperNavigate != NULL);
  1043.     if (pHyperNavigate || pHyperNavigateWithContext)
  1044.     {
  1045.         HX_ASSERT(m_pHyperNavigate == NULL);
  1046.         HX_RELEASE(m_pHyperNavigate);
  1047.         //
  1048.         // Create new hypernaviate interface that knows how to interpret commands.
  1049.         //
  1050.         PlayerHyperNavigate* pPlayerHyperNavigate = new PlayerHyperNavigate;
  1051.         // override the default hypernavigate interface with one that can interpret commands.
  1052.         pPlayerHyperNavigate->AddRef();
  1053.         pPlayerHyperNavigate->Init((IHXPlayer*)this, pHyperNavigate, pHyperNavigateWithContext);
  1054.         m_pHyperNavigate = pPlayerHyperNavigate;
  1055.         // free memory
  1056.         HX_RELEASE(pHyperNavigate);
  1057.         HX_RELEASE(pHyperNavigateWithContext);
  1058.     }
  1059. #endif /* defined(HELIX_FEATURE_HYPER_NAVIGATE) */
  1060. #if defined(HELIX_FEATURE_VIDEO)
  1061.     IHXSiteSupplier*   pSiteSupplier = 0;
  1062.     if (HXR_OK == m_pClient->QueryInterface(IID_IHXSiteSupplier, (void**) &pSiteSupplier))
  1063.     {
  1064.         HX_RELEASE(m_pSiteSupplier);
  1065.         m_pSiteSupplier = pSiteSupplier;
  1066.     }
  1067. #endif /* HELIX_FEATURE_VIDEO */
  1068.     m_pClient->QueryInterface(IID_IHXClientRequestSink, (void**) &m_pClientRequestSink);
  1069.     /* For load testing, we have ASM Manager on a per player basis */
  1070. #if defined(HELIX_FEATURE_ASM)
  1071.     BOOL bLoadTest = FALSE;
  1072.     ReadPrefBOOL(m_pPreferences, "LoadTest", bLoadTest);
  1073.     if (bLoadTest)
  1074.     {
  1075.         HX_ASSERT(m_pASM == NULL);
  1076.         m_pASM = CreateBandwidthManager();
  1077.         if (m_pASM)
  1078.         {
  1079.             m_pASM->AddRef();
  1080.             HX_RELEASE(m_pBandwidthMgr);
  1081.             m_pASM->QueryInterface(IID_IHXBandwidthManager,
  1082.                                    (void**) &m_pBandwidthMgr);
  1083.         }
  1084.     }
  1085. #endif /* HELIX_FEATURE_ASM */
  1086.     return HXR_OK;
  1087. }
  1088. /************************************************************************
  1089.  *      Method:
  1090.  *              HXPlayer::Init
  1091.  *      Purpose:
  1092.  *              Get the interface to the client engine object of which the player
  1093.  *              is a part of.
  1094.  *
  1095.  */
  1096. STDMETHODIMP HXPlayer::Init(IHXClientEngine*  pEngine,
  1097.                              UINT32             unRegistryID,
  1098.                              CHXAudioPlayer*    pAudioPlayer)
  1099. {
  1100.     HX_RESULT   theErr = HXR_OK;
  1101.     IHXBuffer*  pPlayerRegName = NULL;
  1102.     m_pEngine   = (HXClientEngine *) pEngine;
  1103.     m_pAudioPlayer  = pAudioPlayer;
  1104.     m_pCoreMutex = m_pEngine->GetCoreMutex();
  1105.     m_pEngine->m_pPlugin2Handler->QueryInterface(IID_IHXPlugin2Handler,
  1106.                                                  (void**)&m_pPlugin2Handler);
  1107.     if (m_pEngine)
  1108.     {
  1109.         m_pEngine->AddRef();
  1110. #if defined(HELIX_FEATURE_SINKCONTROL)
  1111.         if (m_pAdviseSink)
  1112.         {
  1113.             m_pAdviseSink->Init(m_pEngine);
  1114.         }
  1115.         if (m_pErrorSinkControl)
  1116.         {
  1117.             m_pErrorSinkControl->Init(m_pEngine);
  1118.         }
  1119. #endif /* HELIX_FEATURE_SINKCONTROL */
  1120.         theErr = m_pEngine->QueryInterface(IID_IHXScheduler,
  1121.                                             (void**) &m_pScheduler);
  1122. #if defined(HELIX_FEATURE_ASM)
  1123.         m_pEngine->QueryInterface(IID_IHXBandwidthManager,
  1124.                                             (void**) &m_pBandwidthMgr);
  1125. #endif /* HELIX_FEATURE_ASM */
  1126.         m_pEngine->QueryInterface(IID_IHXClientViewSource,
  1127.                                             (void**)&m_pClientViewSource);
  1128.         m_pEngine->QueryInterface(IID_IHXClientViewRights,
  1129.                                             (void**)&m_pClientViewRights);
  1130.         m_pEngine->QueryInterface(IID_IHXPreferredTransportManager,
  1131.                                             (void**)&m_pPreferredTransportManager);
  1132.         m_pEngine->QueryInterface(IID_IHXNetInterfaces,
  1133.                                             (void**)&m_pNetInterfaces);
  1134. #if defined(HELIX_FEATURE_REGISTRY)
  1135.         // create registry entries
  1136.         if (HXR_OK != m_pEngine->QueryInterface(IID_IHXRegistry, (void**)&m_pRegistry))
  1137.         {
  1138.             m_pRegistry = NULL;
  1139.         }
  1140.         else
  1141. #endif /* HELIX_FEATURE_REGISTRY */
  1142.         {
  1143. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1144.             char        szRegName[MAX_DISPLAY_NAME] = {0}; /* Flawfinder: ignore */
  1145.             m_pStats = new PLAYER_STATS(m_pRegistry, unRegistryID);
  1146.             m_pRegistry->AddInt("Statistics.StreamSwitchOccured", 0);
  1147.             if (m_pRegistry &&
  1148.                 HXR_OK == m_pRegistry->GetPropName(unRegistryID, pPlayerRegName))
  1149.             {
  1150.                 SafeSprintf(szRegName, MAX_DISPLAY_NAME, "%s.Repeat", pPlayerRegName->GetBuffer());
  1151.                 m_ulRepeatedRegistryID = m_pRegistry->AddComp(szRegName);
  1152.                 SafeSprintf(szRegName, MAX_DISPLAY_NAME, "%s.NextGroup", pPlayerRegName->GetBuffer());
  1153.                 m_ulNextGroupRegistryID = m_pRegistry->AddComp(szRegName);
  1154.             }
  1155.             HX_RELEASE(pPlayerRegName);
  1156. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1157. #if defined(HELIX_FEATURE_REGISTRY) && defined(HELIX_FEATURE_MASTERTAC)
  1158.             // create master TAC object
  1159.             UINT32 playerID = 0;
  1160.             GetID(playerID);
  1161.             m_pMasterTAC->SetRegistry(m_pRegistry,playerID);
  1162. #endif /* HELIX_FEATURE_REGISTRY && HELIX_FEATURE_MASTERTAC*/
  1163.         }
  1164.         m_pCookies = m_pEngine->GetCookies();
  1165.     }
  1166.     else
  1167.     {
  1168.         theErr = HXR_INVALID_PARAMETER;
  1169.     }
  1170.     if (m_pAudioPlayer && theErr == HXR_OK)
  1171.     {
  1172.         m_pAudioPlayer->AddRef();
  1173.         theErr = m_pAudioPlayer->Init((IUnknown*) (IHXPlayer*)this);
  1174.     }
  1175. #if defined(HELIX_FEATURE_NEXTGROUPMGR)
  1176.     if (m_pNextGroupManager)
  1177.     {
  1178.         m_pNextGroupManager->Init();
  1179.     }
  1180. #endif /* HELIX_FEATURE_NEXTGROUPMGR */
  1181.     return theErr;
  1182. }
  1183. /************************************************************************
  1184.  *      Method:
  1185.  *              IHXPlayer::IsDone
  1186.  *      Purpose:
  1187.  *              Ask the player if it is done with the current presentation
  1188.  *
  1189.  */
  1190. STDMETHODIMP_ (BOOL) HXPlayer::IsDone(void)
  1191. {
  1192.     return m_bIsPresentationDone;
  1193. }
  1194. /************************************************************************
  1195.  *      Method:
  1196.  *              IHXPlayer::IsLive
  1197.  *      Purpose:
  1198.  *              Ask the player whether it contains the live source
  1199.  *
  1200.  */
  1201. STDMETHODIMP_ (BOOL) HXPlayer::IsLive(void)
  1202. {
  1203.     return m_bIsLive;
  1204. }
  1205. /************************************************************************
  1206.  *      Method:
  1207.  *              IHXPlayer::GetCurrentPlayTime
  1208.  *      Purpose:
  1209.  *              Get the current time on the Player timeline
  1210.  *
  1211.  */
  1212. STDMETHODIMP_ (ULONG32) HXPlayer::GetCurrentPlayTime(void)
  1213. {
  1214.     HX_RESULT theErr = HXR_OK;
  1215.     m_bCoreLocked = TRUE;
  1216.     m_pCoreMutex->Lock();
  1217.     theErr = m_pAudioPlayer->GetCurrentPlayBackTime();
  1218.     m_pCoreMutex->Unlock();
  1219.     m_bCoreLocked = FALSE;
  1220.     return theErr;
  1221. }
  1222. /************************************************************************
  1223.  *      Method:
  1224.  *          IHXPlayer::AddAdviseSink
  1225.  *      Purpose:
  1226.  *          Call this method to add a client advise sink.
  1227.  *
  1228.  */
  1229. STDMETHODIMP HXPlayer::AddAdviseSink   (IHXClientAdviseSink*  pAdviseSink)
  1230. {
  1231. #if defined(HELIX_FEATURE_SINKCONTROL)
  1232.     if (m_pAdviseSink)
  1233.     {
  1234.         return m_pAdviseSink->AddAdviseSink(pAdviseSink);
  1235.     }
  1236.     else
  1237. #endif /* HELIX_FEATURE_SINKCONTROL */
  1238.     {
  1239.         return HXR_NOTIMPL;
  1240.     }
  1241. }
  1242. /************************************************************************
  1243.  *      Method:
  1244.  *          IHXPlayer::RemoveAdviseSink
  1245.  *      Purpose:
  1246.  *          Call this method to remove a client advise sink.
  1247.  */
  1248. STDMETHODIMP HXPlayer::RemoveAdviseSink(IHXClientAdviseSink*  pAdviseSink)
  1249. {
  1250.     HX_RESULT theErr = HXR_OK;
  1251.     m_bCoreLocked = TRUE;
  1252.     m_pCoreMutex->Lock();
  1253. #if defined(HELIX_FEATURE_SINKCONTROL)
  1254.     if (m_pAdviseSink)
  1255.     {
  1256.         theErr = m_pAdviseSink->RemoveAdviseSink(pAdviseSink);
  1257.     }
  1258. #endif /* HELIX_FEATURE_SINKCONTROL */
  1259.     m_pCoreMutex->Unlock();
  1260.     m_bCoreLocked = FALSE;
  1261.     return theErr;
  1262. }
  1263. ULONG32 HXPlayer::GetInst(void)
  1264. {
  1265. #if defined(_WIN32)
  1266.     return (ULONG32)GetModuleHandle(NULL);
  1267. #elif defined(_WIN16)
  1268.     return (ULONG32)g_hInstance;
  1269. #else
  1270.     return 0;
  1271. #endif
  1272. }
  1273. HX_RESULT
  1274. HXPlayer::SetStatsGranularity
  1275. (
  1276.     ULONG32     ulGranularity
  1277. )
  1278. {
  1279. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1280.     m_ulStatsGranularity = ulGranularity;
  1281.     if (m_pUpdateStatsCallback->m_bIsCallbackPending && ALLFS == m_ulStatsGranularity)
  1282.     {
  1283.         m_pUpdateStatsCallback->m_bIsCallbackPending = FALSE;
  1284.         m_pScheduler->Remove(m_pUpdateStatsCallback->m_PendingHandle);
  1285.         m_pUpdateStatsCallback->m_PendingHandle = 0;
  1286.     }
  1287.     else if (!m_pUpdateStatsCallback->m_bIsCallbackPending && ALLFS != m_ulStatsGranularity)
  1288.     {
  1289.         UpdateStatistics();
  1290.     }
  1291.     return HXR_OK;
  1292. #else
  1293.     return HXR_NOTIMPL;
  1294. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1295. }
  1296. STDMETHODIMP
  1297. HXPlayer::ClosePresentation()
  1298. {
  1299.     m_bCoreLocked = TRUE;
  1300.     m_pCoreMutex->Lock();
  1301.     // This stops the player if it is playing and cleans up the layout.
  1302.     StopPlayer(END_STOP);
  1303.     CloseAllRenderers(0);
  1304. #if defined(HELIX_FEATURE_VIDEO)
  1305.     if (m_pSiteSupplier && !m_bBeginChangeLayoutTobeCalled)
  1306.     {
  1307.         m_bBeginChangeLayoutTobeCalled  = TRUE;
  1308.         m_pSiteSupplier->DoneChangeLayout();
  1309.     }
  1310. #endif /* HELIX_FEATURE_VIDEO */
  1311.     m_pCoreMutex->Unlock();
  1312.     m_bCoreLocked = FALSE;
  1313.     return HXR_OK;
  1314. }
  1315. STDMETHODIMP
  1316. HXPlayer::SetMinimumPreroll(UINT32 ulMinPreroll)
  1317. {
  1318.     HX_RESULT hr = HXR_OK;
  1319.     m_ulMinimumTotalPreroll = ulMinPreroll;
  1320.     return hr;
  1321. }
  1322. STDMETHODIMP
  1323. HXPlayer::GetMinimumPreroll(REF(UINT32) ulMinPreroll)
  1324. {
  1325.     HX_RESULT hr = HXR_OK;
  1326.     ulMinPreroll = m_ulMinimumTotalPreroll;
  1327.     return hr;
  1328. }
  1329. HX_RESULT
  1330. HXPlayer::UpdateStatistics(void)
  1331. {
  1332. #if defined(HELIX_FEATURE_STATS) && defined(HELIX_FEATURE_REGISTRY)
  1333.     BOOL                bUpdate = FALSE;
  1334.     ULONG32             ulPlayerTotal = 0;
  1335.     ULONG32             ulPlayerReceived = 0;
  1336.     ULONG32             ulPlayerNormal = 0;
  1337.     ULONG32             ulPlayerRecovered = 0;
  1338.     ULONG32             ulPlayerDuplicate = 0;
  1339.     ULONG32             ulPlayerOutOfOrder = 0;
  1340.     ULONG32             ulPlayerLost = 0;
  1341.     ULONG32             ulPlayerLate = 0;
  1342.     UINT32              ulPlayerTotal30 = 0;
  1343.     UINT32              ulPlayerLost30 = 0;
  1344.     ULONG32             ulPlayerResendRequested = 0;
  1345.     ULONG32             ulPlayerResendReceived = 0;
  1346.     ULONG32             ulPlayerBandwidth = 0;
  1347.     ULONG32             ulPlayerCurBandwidth = 0;
  1348.     ULONG32             ulPlayerAvgBandwidth = 0;
  1349.     INT32               lAvgLatency = 0;
  1350.     INT32               lHighLatency = 0;
  1351.     INT32               lLowLatency = 0xFFFF;
  1352.     ULONG32             ulStreamNumber = 0;
  1353.     SourceInfo*         pSourceInfo = NULL;
  1354.     RendererInfo*       pRenderInfo = NULL;
  1355.     IHXStatistics*     pStatistics = NULL;
  1356.     UINT16              uBufferingMode = 0;
  1357.     CHXMapPtrToPtr::Iterator    ndxSource;
  1358.     CHXMapLongToObj::Iterator   ndxRend;
  1359.     if (!m_bInitialized || m_bPaused)
  1360.     {
  1361.         goto exit;
  1362.     }
  1363.     // update statistics
  1364.     ndxSource = m_pSourceMap->Begin();
  1365.     for (; ndxSource != m_pSourceMap->End(); ++ndxSource)
  1366.     {
  1367.         pSourceInfo = (SourceInfo*) (*ndxSource);
  1368.         // notify the renderer to update its statistics
  1369.         ndxRend = pSourceInfo->m_pRendererMap->Begin();
  1370.         for (; ndxRend != pSourceInfo->m_pRendererMap->End(); ++ndxRend)
  1371.         {
  1372.             pRenderInfo = (RendererInfo*)(*ndxRend);
  1373.             if (pRenderInfo->m_pRenderer &&
  1374.                 HXR_OK == pRenderInfo->m_pRenderer->
  1375.                                 QueryInterface(IID_IHXStatistics,
  1376.                                                 (void**)&pStatistics))
  1377.             {
  1378.                 pStatistics->UpdateStatistics();
  1379.                 pStatistics->Release();
  1380.                 pStatistics = NULL;
  1381.             }
  1382.         }
  1383.         // update each source
  1384.         if (pSourceInfo->m_pSource              &&
  1385.             HXR_OK == pSourceInfo->m_pSource->UpdateStatistics())
  1386.         {
  1387.             ulPlayerTotal           += pSourceInfo->m_pSource->m_pStats->m_pTotal->GetInt();
  1388.             ulPlayerReceived        += pSourceInfo->m_pSource->m_pStats->m_pReceived->GetInt();
  1389.             ulPlayerNormal          += pSourceInfo->m_pSource->m_pStats->m_pNormal->GetInt();
  1390.             ulPlayerRecovered       += pSourceInfo->m_pSource->m_pStats->m_pRecovered->GetInt();
  1391.             ulPlayerDuplicate       += pSourceInfo->m_pSource->m_pStats->m_pDuplicate->GetInt();
  1392.             ulPlayerOutOfOrder      += pSourceInfo->m_pSource->m_pStats->m_pOutOfOrder->GetInt();
  1393.             ulPlayerLost            += pSourceInfo->m_pSource->m_pStats->m_pLost->GetInt();
  1394.             ulPlayerLate            += pSourceInfo->m_pSource->m_pStats->m_pLate->GetInt();
  1395.             ulPlayerResendRequested += pSourceInfo->m_pSource->m_pStats->m_pResendRequested->GetInt();
  1396.             ulPlayerResendReceived  += pSourceInfo->m_pSource->m_pStats->m_pResendReceived->GetInt();
  1397.             ulPlayerTotal30         += pSourceInfo->m_pSource->m_pStats->m_pTotal30->GetInt();
  1398.             ulPlayerLost30          += pSourceInfo->m_pSource->m_pStats->m_pLost30->GetInt();
  1399.             ulPlayerBandwidth       += pSourceInfo->m_pSource->m_pStats->m_pClipBandwidth->GetInt();
  1400.             ulPlayerCurBandwidth    += pSourceInfo->m_pSource->m_pStats->m_pCurBandwidth->GetInt();
  1401.             ulPlayerAvgBandwidth    += pSourceInfo->m_pSource->m_pStats->m_pAvgBandwidth->GetInt();
  1402.             lAvgLatency             += pSourceInfo->m_pSource->m_pStats->m_pAvgLatency->GetInt();
  1403.             if (lHighLatency < pSourceInfo->m_pSource->m_pStats->m_pHighLatency->GetInt())
  1404.             {
  1405.                 lHighLatency = pSourceInfo->m_pSource->m_pStats->m_pHighLatency->GetInt();
  1406.             }
  1407.             if (lLowLatency > pSourceInfo->m_pSource->m_pStats->m_pLowLatency->GetInt())
  1408.             {
  1409.                 lLowLatency = pSourceInfo->m_pSource->m_pStats->m_pLowLatency->GetInt();
  1410.             }
  1411.             if (uBufferingMode < (UINT16) pSourceInfo->m_pSource->m_pStats->m_pBufferingMode->GetInt())
  1412.             {
  1413.                 uBufferingMode = (UINT16) pSourceInfo->m_pSource->m_pStats->m_pBufferingMode->GetInt();
  1414.             }
  1415.             if (pSourceInfo->m_pSource->m_pStatsManager)
  1416.             {
  1417.                 pSourceInfo->m_pSource->m_pStatsManager->Copy();
  1418.             }
  1419.         }
  1420.     }
  1421.     bUpdate = SetIntIfNecessary(m_pStats->m_pTotal, (INT32)ulPlayerTotal);
  1422.     bUpdate |= SetIntIfNecessary(m_pStats->m_pReceived, (INT32)ulPlayerReceived);
  1423.     bUpdate |= SetIntIfNecessary(m_pStats->m_pNormal, (INT32)ulPlayerNormal);
  1424.     bUpdate |= SetIntIfNecessary(m_pStats->m_pRecovered, (INT32)ulPlayerRecovered);
  1425.     bUpdate |= SetIntIfNecessary(m_pStats->m_pDuplicate, (INT32)ulPlayerDuplicate);
  1426.     bUpdate |= SetIntIfNecessary(m_pStats->m_pOutOfOrder, (INT32)ulPlayerOutOfOrder);
  1427.     bUpdate |= SetIntIfNecessary(m_pStats->m_pLost, (INT32)ulPlayerLost);
  1428.     bUpdate |= SetIntIfNecessary(m_pStats->m_pLate, (INT32)ulPlayerLate);
  1429.     bUpdate |= SetIntIfNecessary(m_pStats->m_pTotal30, (INT32)ulPlayerTotal30);
  1430.     bUpdate |= SetIntIfNecessary(m_pStats->m_pLost30, (INT32)ulPlayerLost30);
  1431.     bUpdate |= SetIntIfNecessary(m_pStats->m_pResendRequested, (INT32)ulPlayerResendRequested);
  1432.     bUpdate |= SetIntIfNecessary(m_pStats->m_pResendReceived, (INT32)ulPlayerResendReceived);
  1433.     bUpdate |= SetIntIfNecessary(m_pStats->m_pClipBandwidth, (INT32)ulPlayerBandwidth);
  1434.     bUpdate |= SetIntIfNecessary(m_pStats->m_pCurBandwidth, (INT32)ulPlayerCurBandwidth);
  1435.     bUpdate |= SetIntIfNecessary(m_pStats->m_pAvgBandwidth, (INT32)ulPlayerAvgBandwidth);
  1436.     bUpdate |= SetIntIfNecessary(m_pStats->m_pAvgLatency, (INT32)lAvgLatency);
  1437.     bUpdate |= SetIntIfNecessary(m_pStats->m_pHighLatency, (INT32)lHighLatency);
  1438.     bUpdate |= SetIntIfNecessary(m_pStats->m_pLowLatency, (INT32)lLowLatency);
  1439.     bUpdate |= SetIntIfNecessary(m_pStats->m_pBufferingMode, (INT32)uBufferingMode);
  1440.     if (bUpdate || m_bForceStatsUpdate)
  1441.     {
  1442.         if (m_pAdviseSink)
  1443.         {
  1444.             m_pAdviseSink->OnStatisticsChanged();
  1445.         }
  1446.         m_bForceStatsUpdate = FALSE;
  1447.     }
  1448. exit:
  1449.     if (!m_pUpdateStatsCallback->m_bIsCallbackPending && ALLFS != m_ulStatsGranularity)
  1450.     {
  1451.         m_pUpdateStatsCallback->m_bIsCallbackPending  = TRUE;
  1452.         m_pUpdateStatsCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pUpdateStatsCallback,
  1453.                                                                 m_ulStatsGranularity);
  1454.     }
  1455. #endif /* HELIX_FEATURE_STATS && HELIX_FEATURE_REGISTRY */
  1456.     return HXR_OK;
  1457. }
  1458. HX_RESULT
  1459. HXPlayer::SetupAudioPlayer()
  1460. {
  1461.     HX_RESULT theErr = HXR_OK;
  1462.     HX_ASSERT(m_bInitialized);
  1463. #if defined(THREADS_SUPPORTED) && !defined(_MAC_UNIX)
  1464.     if (m_bUseCoreThread && !m_pEngine->AtInterruptTime())
  1465.     {
  1466.         HX_ASSERT(m_pSetupCallback->GetPendingCallback() == 0);
  1467.         if (!m_pSetupCallback->GetPendingCallback())
  1468.         {
  1469.             m_pSetupCallback->CallbackScheduled(
  1470.             m_pScheduler->RelativeEnter(m_pSetupCallback, 0));
  1471.         }
  1472.         return HXR_OK;
  1473.     }
  1474. #endif /*_WIN32*/
  1475.     m_bSetupToBeDone = FALSE;
  1476.     PrepareAudioPlayer();
  1477. #if defined(THREADS_SUPPORTED) && !defined(_MAC_UNIX)
  1478.     if (m_bUseCoreThread && m_pEngine->AtInterruptTime())
  1479.     {
  1480.         m_pAudioPlayer->UseCoreThread();
  1481.     }
  1482. #endif
  1483.     theErr = m_pAudioPlayer->Setup(m_ulLowestGranularity);
  1484.     if (theErr)
  1485.     {
  1486.         SetLastError(theErr);
  1487.     }
  1488.     if (!theErr)
  1489.     {
  1490.         m_bPostSetupToBeDone = TRUE;
  1491.     }
  1492.     return theErr;
  1493. }
  1494. HX_RESULT
  1495. HXPlayer::PrepareAudioPlayer()
  1496. {
  1497.     return HXR_OK;
  1498. }
  1499. HX_RESULT HXPlayer::ProcessIdle(void)
  1500. {
  1501.     if ((!m_bInitialized || m_bPostSetupToBeDone ) && m_pEngine->AtInterruptTime())
  1502.     {
  1503.         return HXR_OK;
  1504.     }
  1505.     if (m_bCoreLocked)
  1506.     {
  1507.         SchedulePlayer();
  1508.         return HXR_OK;
  1509.     }
  1510.     m_pCoreMutex->Lock();
  1511. #if 0
  1512. #if defined(_WIN32) && defined(_DEBUG)
  1513.     GetChangesToWorkingSet();
  1514. #endif
  1515. #endif
  1516.     m_bCoreLocked   = TRUE;
  1517.     HX_RESULT           theErr              = HXR_OK;
  1518.     BOOL                bIsBuffering        = FALSE;
  1519.     UINT16              uLowestBuffering    = 100;
  1520.     SourceInfo*         pSourceInfo         = NULL;
  1521.     RendererInfo*       pRendInfo           = NULL;
  1522.     IHXRenderer*        pRenderer           = NULL;
  1523.     BOOL                bDone               = FALSE;
  1524.     BOOL                bIsFirst            = TRUE;
  1525.     BOOL                bReadyToUpgrade     = TRUE;
  1526.     BOOL                bSuppressErrorReporting = FALSE;
  1527.     UINT32              ulNumStreamsToBeFilled = 0;
  1528.     UINT32              ulLoopEntryTime     = 0;
  1529.     UINT16              unStatusCode        = 0;
  1530.     UINT16              unPercentDone       = 0;
  1531.     IHXBuffer*          pStatusDesc         = NULL;
  1532.     CHXMapPtrToPtr::Iterator    ndxSource;
  1533.     CHXMapLongToObj::Iterator   ndxRend;
  1534.     if (m_bIsDone || m_bSetupToBeDone)
  1535.     {
  1536.         goto exitRoutine;
  1537.     }
  1538. #ifdef _MACINTOSH
  1539.     /* check InternalPause() for details */
  1540.         if (m_bPendingAudioPause && !m_pEngine->AtInterruptTime())
  1541.         {
  1542.             m_pAudioPlayer->Pause();
  1543.         }
  1544. #endif
  1545.     ndxSource = m_pSourceMap->Begin();
  1546.     for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  1547.     {
  1548.         pSourceInfo     = (SourceInfo*)(*ndxSource);
  1549.         /* Do not call Process source at interrupt time unless
  1550.          * it is initialized.
  1551.          */
  1552.         if (pSourceInfo->m_pSource &&
  1553.             (pSourceInfo->m_pSource->IsInitialized() ||
  1554.             !m_pEngine->AtInterruptTime()))
  1555.         {
  1556.             // XXX HP may need to rework
  1557.             if (!pSourceInfo->m_bDone)
  1558.             {
  1559.                 theErr = pSourceInfo->m_pSource->ProcessIdle();
  1560.                 if( theErr == HXR_OUTOFMEMORY )
  1561.                 {
  1562.                     goto exitRoutine;
  1563.                 }
  1564.             }
  1565.             theErr = SpawnSourceIfNeeded(pSourceInfo);
  1566.             if( theErr == HXR_OUTOFMEMORY )
  1567.             {
  1568.                 goto exitRoutine;
  1569.             }
  1570.             else
  1571.             {
  1572.                 theErr = HXR_OK; // filter out HXR_NOTIMPL
  1573.             }
  1574.         }
  1575.         if (pSourceInfo->m_pPeerSourceInfo                      &&
  1576.             pSourceInfo->m_pPeerSourceInfo->m_pSource           &&
  1577.             !pSourceInfo->m_pPeerSourceInfo->m_bDone            &&
  1578.             (pSourceInfo->m_pPeerSourceInfo->m_pSource->IsInitialized() ||
  1579.             !m_pEngine->AtInterruptTime()))
  1580.         {
  1581.             theErr = pSourceInfo->m_pPeerSourceInfo->m_pSource->ProcessIdle();
  1582.             if( theErr == HXR_OUTOFMEMORY )
  1583.             {
  1584.                 goto exitRoutine;
  1585.             }
  1586.         }
  1587.     }
  1588. #if defined(HELIX_FEATURE_PREFETCH)
  1589.     if (m_pPrefetchManager &&
  1590.         m_pPrefetchManager->GetNumSources() > 0)
  1591.     {
  1592.         m_pPrefetchManager->ProcessIdle();
  1593.     }
  1594. #endif /* HELIX_FEATURE_PREFETCH */
  1595. #if defined(HELIX_FEATURE_NEXTGROUPMGR)
  1596.     if (m_pNextGroupManager->GetNumSources() > 0)
  1597.     {
  1598.         m_pNextGroupManager->ProcessIdle();
  1599.     }
  1600. #endif /* HELIX_FEATURE_NEXTGROUPMGR */
  1601.     // check the status first
  1602.     if (!m_bContactingDone &&
  1603.         HXR_OK == GetStatus(unStatusCode, pStatusDesc, unPercentDone))
  1604.     {
  1605.         if (HX_STATUS_CONTACTING == unStatusCode && pStatusDesc && m_pAdviseSink)
  1606.         {
  1607.             m_pAdviseSink->OnContacting((const char*)pStatusDesc->GetBuffer());
  1608.         }
  1609.         else if (HX_STATUS_INITIALIZING != unStatusCode)
  1610.         {
  1611.             m_bContactingDone = TRUE;
  1612.         }
  1613.         HX_RELEASE(pStatusDesc);
  1614.     }
  1615.     // initialize renderes if not done yet..
  1616.     // this involves reading headers from source object
  1617.     // creating the right renderers for each stream and pass this
  1618.     // header to the renderer.
  1619.     if (!m_bInitialized)
  1620.     {
  1621.         /* A temporary hack till we change SMIL fileformat
  1622.          * to send Layout info in Header
  1623.          */
  1624.         BOOL    bIsSmilRenderer = m_bSetupLayoutSiteGroup;
  1625.         theErr = InitializeRenderers();
  1626. #if defined(HELIX_FEATURE_VIDEO)
  1627.         if (!theErr && m_bInitialized && !m_bPlayerWithoutSources)
  1628.         {
  1629.             SetupLayout(/*!m_bSetupLayoutSiteGroup*/ FALSE);
  1630.             if (bIsSmilRenderer == m_bSetupLayoutSiteGroup &&
  1631.                 m_pSiteSupplier && !m_bBeginChangeLayoutTobeCalled)
  1632.             {
  1633.                 m_bBeginChangeLayoutTobeCalled  = TRUE;
  1634.                 m_pSiteSupplier->DoneChangeLayout();
  1635.             }
  1636.         }
  1637. #endif /* HELIX_FEATURE_VIDEO */
  1638.         if (!theErr && m_bInitialized)
  1639.         {
  1640.             AdjustPresentationTime();
  1641.             m_bSetupToBeDone = TRUE;
  1642.             theErr = SetupAudioPlayer();
  1643.         }
  1644.     }
  1645.     if (m_bPostSetupToBeDone)
  1646.     {
  1647.         m_bPostSetupToBeDone = FALSE;
  1648.         /* Initialize audio services */
  1649.         if (!theErr && m_bInitialized)
  1650.         {
  1651.             m_bIsPresentationClosedToBeSent = TRUE;
  1652.             if (m_pAdviseSink)
  1653.             {
  1654.                 m_pAdviseSink->OnPresentationOpened();
  1655.             }
  1656.         }
  1657.         if (!theErr && m_bInitialized)
  1658.         {
  1659.             m_ulMinimumAudioPreroll = m_pAudioPlayer->GetInitialPushdown();
  1660.             SetMinimumPushdown();
  1661.         }
  1662.         if (!theErr && m_bInitialized && !m_bIsFirstBegin)
  1663.         {
  1664.             CheckSourceRegistration();
  1665.             ndxSource = m_pSourceMap->Begin();
  1666.             for (; !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  1667.             {
  1668.                 SourceInfo* pSourceInfo = (SourceInfo*) (*ndxSource);
  1669.                 HXSource* pSource = pSourceInfo->m_pSource;
  1670.                 
  1671.                 if (pSource)
  1672.                 {
  1673.                     theErr = pSource->DoResume();
  1674.                 }
  1675.                 else
  1676.                 {
  1677.                     /* pSource should never be NULL */
  1678.                     HX_ASSERT(FALSE);
  1679.                 }
  1680.             }
  1681.         }
  1682.         /* Start Downloading even if we have not been issued a
  1683.          * Begin() command
  1684.          */
  1685.         if (!theErr && m_bInitialized && m_bIsFirstBegin && !m_bIsDone)
  1686.         {
  1687.             theErr = StartDownload();
  1688.         }
  1689.     }
  1690.     // if it is still not initialized check error code and return
  1691.     if (theErr || !m_bInitialized)
  1692.     {
  1693.         // my first use of goto..!!
  1694.         goto exitRoutine;
  1695.     }
  1696.     /* try to fill up packets from the various source objects for
  1697.      * different streams so that all of them are upto their preroll
  1698.      * mark...
  1699.      */
  1700.     UpdateCurrentPlayTime( m_pAudioPlayer->GetCurrentPlayBackTime() );
  1701.     if (!m_ToBeginRendererList.IsEmpty())
  1702.     {
  1703.         CheckBeginList();
  1704.     }
  1705.     while (!theErr && !bDone && m_uNumSourcesActive > 0)
  1706.     {
  1707.         ndxSource = m_pSourceMap->Begin();
  1708.         for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  1709.         {
  1710.             pSourceInfo = (SourceInfo*)(*ndxSource);
  1711.             theErr = pSourceInfo->ProcessIdle(bIsFirst, ulNumStreamsToBeFilled,
  1712.                                        bIsBuffering, uLowestBuffering);
  1713.             if (pSourceInfo->m_pPeerSourceInfo)
  1714.             {
  1715.                 BOOL    tmp_bIsFirst = TRUE;
  1716.                 BOOL    tmp_bIsBuffering = FALSE;
  1717.                 UINT32  tmp_ulNumStreamsToBeFilled = 0;
  1718.                 UINT16  tmp_uLowestBuffering = 100;
  1719.                 pSourceInfo->m_pPeerSourceInfo->ProcessIdle(tmp_bIsFirst, tmp_ulNumStreamsToBeFilled,
  1720.                                                             tmp_bIsBuffering, tmp_uLowestBuffering);
  1721.             }
  1722.             /* Someone added a source during ProcessIdle.
  1723.              * Start all over again
  1724.              */
  1725.             if (m_bSourceMapUpdated)
  1726.             {
  1727.                 break;
  1728.             }
  1729.         }
  1730.         if (bIsBuffering && !m_bIsPlaying)
  1731.         {
  1732.             if (!ulLoopEntryTime)
  1733.             {
  1734.                 ulLoopEntryTime = HX_GET_TICKCOUNT();
  1735.             }
  1736.             ndxSource = m_pSourceMap->Begin();
  1737.             for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  1738.             {
  1739.             pSourceInfo = (SourceInfo*)(*ndxSource);
  1740.             ndxRend = pSourceInfo->m_pRendererMap->Begin();
  1741.             for (;!theErr && ndxRend != pSourceInfo->m_pRendererMap->End();
  1742.                     ++ndxRend)
  1743.             {
  1744.                 pRendInfo   = (RendererInfo*)(*ndxRend);
  1745.                 pRenderer   = pRendInfo->m_pRenderer;
  1746.                 if((pRendInfo->m_bInterruptSafe || !m_pEngine->AtInterruptTime())
  1747.                    && pRenderer)
  1748.                 {
  1749.                     pRenderer->OnBuffering(m_BufferingReason, uLowestBuffering);
  1750.                 }
  1751.             }
  1752.             }
  1753.             m_b100BufferingToBeSent = TRUE;
  1754.             if (m_pAdviseSink)
  1755.             {
  1756.                 m_pAdviseSink->OnBuffering(m_BufferingReason, uLowestBuffering);
  1757.             }
  1758.             // free some CPU time if we stuck in this WHILE loop too long
  1759.             if (!theErr &&
  1760.                 CALCULATE_ELAPSED_TICKS(ulLoopEntryTime, HX_GET_TICKCOUNT()) >= MAX_LOOP_EXE_TIME)
  1761.             {
  1762.                 break;
  1763.             }
  1764.             if (!theErr)
  1765.             {
  1766.                 theErr = ProcessCurrentEvents();
  1767.             }
  1768.         }
  1769.         if (theErr || m_bSourceMapUpdated)
  1770.         {
  1771.             m_bSourceMapUpdated = FALSE;
  1772.             goto exitRoutine;
  1773.         }
  1774.         bIsFirst = FALSE;
  1775.         if (ulNumStreamsToBeFilled == 0)
  1776.         {
  1777.             bDone = TRUE;
  1778.         }
  1779.     }
  1780.     // SPECIAL CASE:
  1781.     // the player received all the packets(m_uNumSourcesActive is 0) and
  1782.     // EndOfPacket() hasn't been sent to the renderer yet,
  1783.     // BUT the renderer still calls ReportRebufferStatus()
  1784.     // we need to make sure the rebuffering is done before calling resume.
  1785.     if (m_uNumSourcesActive == 0)
  1786.     {
  1787.         ndxSource = m_pSourceMap->Begin();
  1788.         for (;!theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  1789.         {
  1790.             pSourceInfo = (SourceInfo*)(*ndxSource);
  1791.             if (!pSourceInfo->IsRebufferDone())
  1792.             {
  1793.                 bIsBuffering = TRUE;
  1794.                 break;
  1795.             }
  1796.         }
  1797.     }
  1798.     /* Stop Downloading if we have not been issued a
  1799.      * Begin() command and we are done with Buffering.
  1800.      */
  1801.     if (!theErr && !bIsBuffering && m_bFastStartInProgress && !m_bIsDone)
  1802.     {
  1803.         theErr = PauseDownload();
  1804.     }
  1805.     // Process Current Events Due...
  1806.     if (!theErr)
  1807.     {
  1808.         theErr = ProcessCurrentEvents();
  1809.     }
  1810.     // repeat source specific
  1811.     SwitchSourceIfNeeded();
  1812.     if (!theErr && !bIsBuffering &&
  1813.         (!m_bResumeOnlyAtSystemTime || !m_pEngine->AtInterruptTime()))
  1814.     {
  1815.         theErr = CheckForAudioResume();
  1816.     }
  1817.     if (!theErr && !m_bLastGroup && !m_bNextGroupStarted && !m_pEngine->AtInterruptTime())
  1818.     {
  1819.         CheckToStartNextGroup();
  1820.     }
  1821.     /* Check if live stream has ended */
  1822.     if (!theErr && m_bInitialized && !m_bPlayerWithoutSources &&
  1823.         ((!m_bIsLive && (!m_ulPresentationDuration ||
  1824.         (m_ulPresentationDuration < m_ulCurrentPlayTime))) ||
  1825.         (m_bIsLive && AreAllPacketsSent())) &&
  1826.         m_uNumSourcesActive == 0)
  1827.     {
  1828.         /* If there are any sources that MUST be initialized before playback
  1829.          * begins/stops, we should not end the presentation here. Instead, wait for
  1830.          * the stream headers to come down...
  1831.          */
  1832.         if ((m_uNumSourceToBeInitializedBeforeBegin > 0) &&
  1833.             m_ulPresentationDuration)
  1834.         {
  1835.             InternalPause();
  1836.         }
  1837.         else if (!m_ulPresentationDuration ||
  1838.                  (m_ulPresentationDuration < m_ulCurrentPlayTime))
  1839.         {
  1840.             if (ScheduleOnTimeSync())
  1841.             {
  1842.                 // schedule a system callback to ensure
  1843.                 // the renderers receive OnTimeSync() on its duration
  1844.                 // AND the clip ends ASAP
  1845.                 RemovePendingCallback(m_pHXPlayerCallback);
  1846.                 m_pHXPlayerCallback->CallbackScheduled(
  1847.                         m_pScheduler->RelativeEnter(m_pHXPlayerCallback, 0));
  1848.                 goto cleanup;
  1849.             }
  1850.             else
  1851.             {
  1852.                 m_bIsDone = TRUE;
  1853.                 m_pAudioPlayer->DonePlayback();
  1854.                 /* This assert is to find bugs in fileformats which place invalid ts
  1855.                  * (ts > m_ulPresentationDuration) on the packets.
  1856.                  */
  1857.                 HX_ASSERT(AreAllPacketsSent() == TRUE);
  1858.             }
  1859.         }
  1860.     }
  1861. exitRoutine:
  1862. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  1863.     if(m_pUpgradeCollection && m_pUpgradeCollection->GetCount() > 0 && !m_pEngine->AtInterruptTime())
  1864.     {
  1865.         // Request an upgrade
  1866.         IHXUpgradeHandler* pUpgradeHandler = NULL;
  1867.         if(m_pClient)
  1868.             m_pClient->QueryInterface(IID_IHXUpgradeHandler, (void**)&pUpgradeHandler);
  1869.         if(!pUpgradeHandler)
  1870.         {
  1871.             // In case of clients with no IHXUpgradeHandler support
  1872.             // just remove all the upgrade collectopn components
  1873.             m_pUpgradeCollection->RemoveAll();
  1874.         theErr = HXR_MISSING_COMPONENTS;
  1875.         }
  1876.         else
  1877.         {
  1878.             // see if we should send an upgrade request only if all the sources
  1879.             // have been initialized...
  1880.             ndxSource = m_pSourceMap->Begin();
  1881.             for (;ndxSource != m_pSourceMap->End(); ++ndxSource)
  1882.             {
  1883.                 pSourceInfo = (SourceInfo*)(*ndxSource);
  1884.                 if (!pSourceInfo->m_bLoadPluginAttempted &&
  1885.                     pSourceInfo->m_pSource &&
  1886.                     pSourceInfo->m_pSource->GetLastError() == HXR_OK)
  1887.                 {
  1888.                     bReadyToUpgrade = FALSE;
  1889.                     break;
  1890.                 }
  1891.             }
  1892.             if (bReadyToUpgrade)
  1893.             {
  1894.                 // Request an upgrade
  1895.                 IHXUpgradeHandler* pUpgradeHandler = NULL;
  1896.                 if(m_pClient)
  1897.                     m_pClient->QueryInterface(IID_IHXUpgradeHandler, (void**)&pUpgradeHandler);
  1898.                 if(pUpgradeHandler)
  1899.                 {
  1900.                     HX_RESULT hr = HXR_MISSING_COMPONENTS;
  1901.                     m_bIsPresentationClosedToBeSent = TRUE;
  1902.                     HX_RESULT nUpgradeResult = pUpgradeHandler->RequestUpgrade(m_pUpgradeCollection, FALSE);
  1903.                     if(nUpgradeResult == HXR_OK || nUpgradeResult == HXR_CANCELLED)
  1904.                     {
  1905.                         // We want to stop playback but we dont want error
  1906.                         // to be reported untill upgrade tries to fix situation.
  1907.                         hr = HXR_OK;
  1908.                         bSuppressErrorReporting = TRUE;
  1909.                     }
  1910.                     m_bIsDone = TRUE;
  1911.                     m_pAudioPlayer->DonePlayback();
  1912.                     m_LastError = hr;
  1913.                 }
  1914.                 HX_RELEASE(pUpgradeHandler);
  1915.                 m_pUpgradeCollection->RemoveAll();
  1916.             }
  1917.             else
  1918.             {
  1919.                 /* We are not done yet... Wait till all the sources have been
  1920.                  * attempted to load required plugins
  1921.                  */
  1922.                 m_bIsDone = FALSE;
  1923.             }
  1924.         }
  1925.     }
  1926. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  1927.     if (!theErr && m_pAltURLs && m_pAltURLs->GetCount() && !m_pEngine->AtInterruptTime())
  1928.     {
  1929.         theErr = DoAltURL();
  1930.     }
  1931.     if (!theErr && m_pRedirectList && m_pRedirectList->GetCount() && !m_pEngine->AtInterruptTime())
  1932.     {
  1933.         theErr = DoRedirect();
  1934.     }
  1935.     if (!theErr && m_bIsDone && !m_bTimeSyncLocked && !m_pEngine->AtInterruptTime())
  1936.     {
  1937.         if (m_LastError != HXR_OK)
  1938.         {
  1939.             m_bIsDone = FALSE;
  1940.             PausePlayer(FALSE);
  1941.             m_bIsDone = TRUE;
  1942.             ActualReport(m_LastSeverity, m_LastError,
  1943.                    m_ulLastUserCode, m_pLastUserString, m_pLastMoreInfoURL);
  1944.             ResetError();
  1945.         }
  1946.         PlayNextGroup();
  1947.     }
  1948.     if (!theErr)
  1949.     {
  1950.         ProcessIdleExt();
  1951.     }
  1952.     SchedulePlayer();
  1953.     /* this error is crucial...need to be reported upto ragui...*/
  1954.     if (theErr && !bSuppressErrorReporting)
  1955.     {
  1956.         SetLastError(theErr);
  1957.     }
  1958. cleanup:
  1959.     m_bCoreLocked   = FALSE;
  1960.     m_pCoreMutex->Unlock();
  1961.     return theErr;
  1962. }
  1963. HX_RESULT
  1964. HXPlayer::ProcessIdleExt(void)
  1965. {
  1966.     return HXR_OK;
  1967. }
  1968. HX_RESULT
  1969. HXPlayer::DoAltURL(void)
  1970. {
  1971. #if defined(HELIX_FEATURE_ALT_URL)
  1972.     HX_RESULT           hr                  = HXR_OK;
  1973.     BOOL                bDefault            = FALSE;
  1974.     char*               pAltURL             = NULL;
  1975.     SourceInfo*         pMainSourceInfo     = NULL;
  1976.     HXSource*          pSource             = NULL;
  1977.     ResetError();
  1978.     while (!hr && m_pAltURLs->GetCount())
  1979.     {
  1980.         pMainSourceInfo = (SourceInfo*) m_pAltURLs->RemoveHead();
  1981. #if defined(HELIX_FEATURE_NEXTGROUPMGR)
  1982.         if (pMainSourceInfo->m_pSource->IsPartOfNextGroup())
  1983.         {
  1984.             m_pNextGroupManager->RemoveSource(pMainSourceInfo);
  1985.             m_bPartOfNextGroup = TRUE;
  1986.         }
  1987.         else
  1988. #endif /* HELIX_FEATURE_NEXTGROUPMGR */
  1989. #if defined(HELIX_FEATURE_PREFETCH)
  1990.         if (pMainSourceInfo->m_pSource->IsPartOfPrefetchGroup())
  1991.         {
  1992.             m_pPrefetchManager->RemoveSource(pMainSourceInfo);
  1993.         }
  1994.         else
  1995. #endif /* HELIX_FEATURE_PREFETCH */
  1996.         {
  1997.             m_pSourceMap->RemoveKey(pMainSourceInfo->m_pSource);
  1998.             m_bSourceMapUpdated = TRUE;
  1999.         }
  2000.         if (pMainSourceInfo->m_bTobeInitializedBeforeBegin &&
  2001.             m_uNumSourceToBeInitializedBeforeBegin > 0)
  2002.         {
  2003.             m_uNumSourceToBeInitializedBeforeBegin--;
  2004.         }
  2005.         pAltURL = pMainSourceInfo->m_pSource->GetAltURL(bDefault);
  2006.         HX_ASSERT(pAltURL);
  2007.         pMainSourceInfo->Stop();
  2008. #if defined(HELIX_FEATURE_NESTEDMETA)
  2009.         HXPersistentComponent* pRootPersistentComponent = m_pPersistentComponentManager->m_pRootPersistentComponent;
  2010.         // only cleanup the layout if
  2011.         // * it's not a SMIL presentation OR
  2012.         // * the AltURL is on the root SMIL presentation itself
  2013.         // in other words
  2014.         // * don't cleanup the layout if the AltURL is on the tracks
  2015.         // * within the SMIL presentation
  2016.         UINT32                 ulPCID = pMainSourceInfo->m_ulPersistentComponentID;
  2017.         HXPersistentComponent* pPersistentComponent = NULL;
  2018.         PersistentType         SourceType = PersistentUnknown;
  2019.         
  2020.         m_pPersistentComponentManager->GetPersistentComponent(ulPCID,
  2021.                                                               (IHXPersistentComponent*&)pPersistentComponent
  2022.                                                               );
  2023.         if( pPersistentComponent )
  2024.             SourceType = (PersistentType)pPersistentComponent->m_ulPersistentType;
  2025.         
  2026.         HX_RELEASE(pPersistentComponent);
  2027.         
  2028.         if( !pRootPersistentComponent  ||
  2029.             SourceType != PersistentSMIL ||
  2030.             pRootPersistentComponent->m_pSourceInfo == pMainSourceInfo)
  2031.         {
  2032.             CleanupLayout();
  2033.             if (pRootPersistentComponent)
  2034.             {
  2035.                 pRootPersistentComponent->m_bCleanupLayoutCalled = TRUE;
  2036.             }
  2037.         }
  2038. #endif /* HELIX_FEATURE_NESTEDMETA */
  2039.         pMainSourceInfo->CloseRenderers();
  2040.         if (pAltURL)
  2041.         {
  2042.             hr = DoAltURLOpen(pAltURL, bDefault, pMainSourceInfo);
  2043.         }
  2044.         m_bPartOfNextGroup = FALSE;
  2045.         HX_VECTOR_DELETE(pAltURL);
  2046.         HX_DELETE(pMainSourceInfo);
  2047.     }
  2048.     return hr;
  2049. #else
  2050.     return HXR_NOTIMPL;
  2051. #endif /* HELIX_FEATURE_ALT_URL */
  2052. }
  2053. HX_RESULT
  2054. HXPlayer::DoRedirect(void)
  2055. {
  2056.     HX_RESULT               hr                          = HXR_OK;
  2057.     BOOL                    bNoRedirectSupport          = FALSE;
  2058.     BOOL                    bBegin                      = m_bUserHasCalledBegin;
  2059.     BOOL                    bRAMOnly                    = TRUE;
  2060.     SourceInfo*             pSourceInfo                 = NULL;
  2061.     RedirectInfo*           pRedirectInfo               = NULL;
  2062.     IHXValues*              pRequestHeaders             = NULL;
  2063.     HXPersistentComponent*  pRootPersistentComponent    = NULL;
  2064.     HXPersistentComponent*  pPersistentComponent        = NULL;
  2065.     m_bDoRedirect = TRUE;
  2066.     pRedirectInfo = (RedirectInfo*) m_pRedirectList->RemoveHead();
  2067. #if defined(HELIX_FEATURE_NESTEDMETA)
  2068.     pRootPersistentComponent = m_pPersistentComponentManager->m_pRootPersistentComponent;
  2069.     if (pRootPersistentComponent)
  2070.     {
  2071.         // no redirect support by default
  2072.         bNoRedirectSupport = TRUE;
  2073.         // except the live source within a RAM
  2074.         GetSourceInfo(pRedirectInfo->m_nGroupID, pRedirectInfo->m_nTrackID, pSourceInfo);
  2075.         if (pSourceInfo)
  2076.         {
  2077.             m_pPersistentComponentManager->GetPersistentComponent(pSourceInfo->m_ulPersistentComponentID,
  2078.                                                                  (IHXPersistentComponent*&)pPersistentComponent);
  2079.             // allow redirect on the root persistent component(i.e. SMIL/RAM)
  2080.             if (pPersistentComponent == pRootPersistentComponent)
  2081.             {
  2082.                 bNoRedirectSupport = FALSE;
  2083.             }
  2084.             else
  2085.             {
  2086.                 while (pPersistentComponent != pRootPersistentComponent)
  2087.                 {
  2088.                     if (PersistentSMIL == pPersistentComponent->m_ulPersistentType)
  2089.                     {
  2090.                         bRAMOnly = FALSE;
  2091.                         break;
  2092.                     }
  2093.                     pPersistentComponent = pPersistentComponent->m_pPersistentParent;
  2094.                 }
  2095.                 if (pRootPersistentComponent->m_ulPersistentType == PersistentRAM   &&
  2096.                     bRAMOnly                                                        &&
  2097.                     pSourceInfo->m_pSource                                          &&
  2098.                     pSourceInfo->m_pSource->IsLive())
  2099.                 {
  2100.                     bNoRedirectSupport = FALSE;
  2101.                 }
  2102.             }
  2103.             HX_RELEASE(pPersistentComponent);
  2104.         }
  2105.         else
  2106.         {
  2107.             HX_ASSERT(FALSE);
  2108.         }
  2109.     }
  2110. #endif /* HELIX_FEATURE_NESTEDMETA */
  2111.     // no Redirect support for SMIL presentation for now
  2112.     // return HXR_SERVER_DISCONNECTED instead
  2113.     if (bNoRedirectSupport)
  2114.     {
  2115.         Report(HXLOG_ERR, HXR_SERVER_DISCONNECTED, HXR_OK, NULL, NULL);
  2116.         goto cleanup;
  2117.     }
  2118.     if (m_pRequest)
  2119.         m_pRequest->GetRequestHeaders(pRequestHeaders);
  2120.     // Set the redirecting property to true before calling stop so the TLC can tell if a redirect is going to occur
  2121.     if (pRequestHeaders)
  2122.         pRequestHeaders->SetPropertyULONG32("IsRedirecting", TRUE);
  2123.     StopPlayer(END_REDIRECT);
  2124.     CloseAllRenderers(m_nCurrentGroup);
  2125.     // Set the redirecting property to false before opening the new URL.
  2126.     if (pRequestHeaders)
  2127.     {
  2128.         pRequestHeaders->SetPropertyULONG32("IsRedirecting", FALSE);
  2129.         HX_RELEASE(pRequestHeaders);
  2130.     }
  2131.     hr = OpenRedirect(pRedirectInfo->m_pURL);
  2132.     if (hr == HXR_OK && bBegin)
  2133.     {
  2134.         Begin();
  2135.     }
  2136. cleanup:
  2137.     HX_DELETE(pRedirectInfo);
  2138.     m_bDoRedirect = FALSE;
  2139.     return hr;
  2140. }
  2141. HX_RESULT
  2142. HXPlayer::OpenRedirect(const char* pszURL)
  2143. {
  2144.     HX_RESULT   hr = HXR_OK;
  2145.     // we want to protect against the TLC opening another URL
  2146.     if (m_bSetModal)
  2147.     {
  2148.         return HXR_OK;
  2149.     }
  2150.     HX_RELEASE(m_pRequest);
  2151.     // get the compresses URL
  2152.     CHXURL url(pszURL);
  2153.     m_pRequest = new CHXRequest();
  2154.     if( m_pRequest )
  2155.     {
  2156.         m_pRequest->AddRef();
  2157.         m_pRequest->SetURL(url.GetURL());
  2158.         m_bActiveRequest = TRUE;
  2159.         hr = DoURLOpen(&url, NULL);
  2160.     }
  2161.     else
  2162.     {
  2163.         hr = HXR_OUTOFMEMORY;
  2164.     }
  2165.     return hr;
  2166. }
  2167. HX_RESULT
  2168. HXPlayer::StartDownload()
  2169. {
  2170.     HX_RESULT                   theErr = HXR_OK;
  2171.     CHXMapPtrToPtr::Iterator    ndxSource;
  2172.     if (!m_bIsDone)
  2173.     {
  2174.         CheckSourceRegistration();
  2175.         ndxSource = m_pSourceMap->Begin();
  2176.         /* Check if we are done. This may be TRUE for empty files */
  2177.         for (; !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  2178.         {
  2179.             SourceInfo* pSourceInfo = (SourceInfo*) (*ndxSource);
  2180.             HXSource* pSource = pSourceInfo->m_pSource;
  2181.             
  2182.             if(pSource && pSource->CanBeResumed())
  2183.             {
  2184.                 theErr = pSource->StartInitialization();
  2185.             }
  2186.         }
  2187.     }
  2188.     m_bFastStartInProgress  = TRUE;
  2189.     m_bFSBufferingEnd       = FALSE;
  2190.     return theErr;
  2191. }
  2192. HX_RESULT
  2193. HXPlayer::PauseDownload(void)
  2194. {
  2195.     HX_RESULT                   theErr = HXR_OK;
  2196.     CHXMapPtrToPtr::Iterator    ndxSource;
  2197.     if (!m_bFSBufferingEnd)
  2198.     {
  2199.         m_bFSBufferingEnd       = TRUE;
  2200.         m_ulFSBufferingEndTime  = HX_GET_TICKCOUNT();
  2201.         /* In network case, we want to buffer extra 2-3 seconds worth
  2202.          * of data. We renter this function over and over again in the
  2203.          * else clause and ultimately send 100% buffering message.
  2204.          * In local playback however, we want to send this message
  2205.          * right away. So do not return the function from here, instead fall
  2206.          * down below to return 100% buffering message instantly
  2207.          */
  2208.         if (!m_bAllLocalSources)
  2209.         {
  2210.             return HXR_OK;
  2211.         }
  2212.     }
  2213.     else
  2214.     {
  2215.         /* Buffer extra 3 seconds worth of data before pausing */
  2216.         if (CALCULATE_ELAPSED_TICKS(m_ulFSBufferingEndTime, HX_GET_TICKCOUNT())
  2217.             < 3000)
  2218.         {
  2219.             return HXR_OK;
  2220.         }
  2221.     }
  2222.     m_bFastStartInProgress  = FALSE;
  2223.     ndxSource = m_pSourceMap->Begin();
  2224.     /* Check if we are done. This may be TRUE for empty files */
  2225.     for (; !theErr && !m_bIsDone && ndxSource != m_pSourceMap->End(); ++ndxSource)
  2226.     {
  2227.         SourceInfo* pSourceInfo = (SourceInfo*) (*ndxSource);
  2228.         HXSource* pSource = pSourceInfo->m_pSource;
  2229.         /* Do not pause a live source */
  2230.         if(!pSource || pSource->IsLive())
  2231.         {
  2232.             continue;
  2233.         }
  2234.         theErr = pSource->DoPause();
  2235.     }
  2236.     if (m_b100BufferingToBeSent)
  2237.     {
  2238.         m_b100BufferingToBeSent = FALSE;
  2239.         if (m_pAdviseSink)
  2240.         {
  2241.             m_pAdviseSink->OnBuffering(m_BufferingReason, 100);
  2242.         }
  2243.     }
  2244.     return theErr;
  2245. }
  2246. void
  2247. HXPlayer::SchedulePlayer(void)
  2248. {
  2249.     if ((!m_bIsDone || m_LastError || m_pEngine->AtInterruptTime()) &&
  2250.         !m_pHXPlayerCallback->GetPendingCallback())
  2251.     {
  2252.         m_pHXPlayerCallback->CallbackScheduled(
  2253.             m_pScheduler->RelativeEnter(m_pHXPlayerCallback, 300));
  2254.     }
  2255.     if ((!m_bIsDone || m_LastError) &&
  2256.         !m_pHXPlayerInterruptCallback->GetPendingCallback())
  2257.     {
  2258.         m_pHXPlayerInterruptCallback->CallbackScheduled(
  2259.             m_pScheduler->RelativeEnter(m_pHXPlayerInterruptCallback, 100));
  2260.     }
  2261. }
  2262. HX_RESULT
  2263. HXPlayer::CheckForAudioResume(void)
  2264. {
  2265.     HX_RESULT theErr = HXR_OK;
  2266.     if (m_bInitialized && !m_bSetupToBeDone && !m_bPaused &&
  2267.         (m_bBeginPending || m_bTimelineToBeResumed) &&
  2268.         m_uNumSourceToBeInitializedBeforeBegin == 0)
  2269.     {
  2270.         if (m_b100BufferingToBeSent)
  2271.         {
  2272.             m_b100BufferingToBeSent = FALSE;
  2273.             if (m_pAdviseSink)
  2274.             {
  2275.                 m_pAdviseSink->OnBuffering(m_BufferingReason, 100);
  2276.             }
  2277.         }
  2278.         /*
  2279.          * change the state of buffering since we have crossed
  2280.          * initial startup state...
  2281.          * BUFFERING_SEEK and BUFFERING_LIVE_PAUSE are handled in OnTimeSync
  2282.          */
  2283.         if (m_BufferingReason == BUFFERING_START_UP)
  2284.         {
  2285.             m_BufferingReason = BUFFERING_CONGESTION;
  2286.         }
  2287.         /* did someone pause/stop the player within 100% OnBuffering call?
  2288.          * if so, do not resume the timeline yet.
  2289.          */
  2290.         if (m_bPaused || !m_bInitialized)
  2291.         {
  2292.             return HXR_OK;
  2293.         }
  2294.         m_bIsPlaying            = TRUE;
  2295.         m_bBeginPending         = FALSE;
  2296.         m_bTimelineToBeResumed  = FALSE;
  2297.         m_bPendingAudioPause    = FALSE;
  2298.         DEBUG_OUT(this, DOL_TRANSPORT, (s,"Audio Resumed"));
  2299.         theErr = m_pAudioPlayer->Resume();
  2300.     }
  2301.     return theErr;
  2302. }
  2303. void HXPlayer::SetMinimumPushdown()
  2304. {
  2305.     UINT32 ulMinimumStartingPreroll = m_ulMinimumAudioPreroll;
  2306. #ifndef HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
  2307.     // This is removed for HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES
  2308.     // (MIN_HEAP) builds because this code will return a shorter
  2309.     // preroll value than is required for proper playback. This will cause
  2310.     // rebuffers with renderers that are driven by OnDryNotification()
  2311.     // because the core will not provide the renderer with packets early
  2312.     // enough. By removing this call the core will use the proper preroll
  2313.     // value and packets will be provided to the renderer in time to
  2314.     // satisfy all OnDryNotification() calls
  2315.     if (m_pAudioPlayer)
  2316.     {
  2317.         ulMinimumStartingPreroll = m_pAudioPlayer->GetInitialPushdown(TRUE);
  2318.     }
  2319. #endif /* HELIX_CONFIG_MIN_PCM_PUSHDOWN_BYTES */
  2320.     CHXMapPtrToPtr::Iterator ndxSource = m_pSourceMap->Begin();
  2321.     for (;  ndxSource != m_pSourceMap->End(); ++ndxSource)
  2322.     {
  2323.         SourceInfo* pSourceInfo = (SourceInfo*)(*ndxSource);
  2324.         HXSource* pSource = pSourceInfo->m_pSource;
  2325.         pSource->SetMinimumPreroll(m_ulMinimumAudioPreroll, ulMinimumStartingPreroll);
  2326.     }
  2327. }
  2328. void
  2329. HXPlayer::ResetError(void)
  2330. {
  2331.     m_LastSeverity      = HXLOG_ERR;
  2332.     m_LastError         = HXR_OK;
  2333.     m_ulLastUserCode    = HXR_OK;
  2334.     HX_VECTOR_DELETE(m_pLastUserString);
  2335.     HX_VECTOR_DELETE(m_pLastMoreInfoURL);
  2336. }
  2337. void
  2338. HXPlayer::SetLastError(HX_RESULT theErr)
  2339. {
  2340.     if (theErr && !m_LastError)
  2341.     {
  2342.         m_LastError = theErr;
  2343.         m_bIsDone   = TRUE;
  2344.         m_pAudioPlayer->DonePlayback();
  2345.     }
  2346.     // Handle OOM errors as special case: we do not want to continue playback
  2347.     // any longer.
  2348.     // Add SLOW_MACHINE to the "Abort Now" category.
  2349.     if( theErr == HXR_OUTOFMEMORY || theErr == HXR_SLOW_MACHINE )
  2350.     {
  2351.         // ActualReport does not get called next time in ProcessIdle because
  2352.         // we Abort playback here, so have to call it manually.
  2353.         ActualReport(m_LastSeverity, m_LastError,
  2354.                      m_ulLastUserCode, m_pLastUserString, m_pLastMoreInfoURL);
  2355.         AbortPlayer();
  2356.     }
  2357. }
  2358. void
  2359. HXPlayer::ResetRedirectList(void)
  2360. {
  2361.     RedirectInfo*   pRedirectInfo = NULL;
  2362.     if (m_pRedirectList)
  2363.     {
  2364.         CHXSimpleList::Iterator  i = m_pRedirectList->Begin();
  2365.         for (; i != m_pRedirectList->End(); ++i)
  2366.         {
  2367.             pRedirectInfo = (RedirectInfo*) (*i);
  2368.             HX_DELETE(pRedirectInfo);
  2369.         }
  2370.         m_pRedirectList->RemoveAll();
  2371.     }
  2372. }
  2373. HX_RESULT
  2374. HXPlayer::HandleRedirectRequest(UINT16 nGroup, UINT16 nTrack, char* pURL)
  2375. {
  2376.     HX_RESULT       theErr = HXR_OK;
  2377.     RedirectInfo*   pRedirectInfo = NULL;
  2378.     if (!m_pRedirectList)
  2379.     {
  2380.         m_pRedirectList = new CHXSimpleList();
  2381.         if (!m_pRedirectList)
  2382.         {
  2383.             theErr = HXR_OUTOFMEMORY;
  2384.             goto cleanup;
  2385.         }
  2386.     }
  2387.     pRedirectInfo = new RedirectInfo;
  2388.     pRedirectInfo->m_pURL = new char[strlen(pURL)+1];
  2389.     strcpy(pRedirectInfo->m_pURL, pURL); /* Flawfinder: ignore */
  2390.     pRedirectInfo->m_nGroupID = nGroup;
  2391.     pRedirectInfo->m_nTrackID = nTrack;
  2392.     m_pRedirectList->AddTail(pRedirectInfo);
  2393. cleanup:
  2394.     return theErr;
  2395. }
  2396. BOOL
  2397. HXPlayer::IsAtSourceMap(SourceInfo* pSourceInfo)
  2398. {
  2399.     SourceInfo* pResult = NULL;
  2400.     return m_pSourceMap->Lookup(pSourceInfo->m_pSource, (void*&)pResult);
  2401. }
  2402. /*
  2403. * IHXErrorMessages methods
  2404. */
  2405. STDMETHODIMP
  2406. HXPlayer::Report
  2407. (
  2408.     const UINT8 unSeverity,
  2409.     HX_RESULT   ulHXCode,
  2410.     const ULONG32       ulUserCode,
  2411.     const char* pUserString,
  2412.     const char* pMoreInfoURL
  2413. )
  2414. {
  2415.     /* Always pass through info and debug messages.
  2416.      * We use these severity levels for logging purposes and
  2417.      * do not consider them as errors
  2418.      */
  2419.     if (unSeverity == HXLOG_INFO    ||
  2420.         unSeverity == HXLOG_DEBUG   ||
  2421.         ulHXCode  == HXR_OK)
  2422.     {
  2423.         return ActualReport(unSeverity, ulHXCode, ulUserCode,
  2424.                             pUserString, pMoreInfoURL);
  2425.     }
  2426.     /* Do not override an error if it is already set.
  2427.      */
  2428.     if (m_LastError != HXR_OK)
  2429.     {
  2430.         m_bIsDone = TRUE;
  2431.         return HXR_OK;
  2432.     }
  2433.     m_LastSeverity      = unSeverity;
  2434.     m_ulLastUserCode    = ulUserCode;
  2435.     SetLastError(ulHXCode);
  2436.     if (pUserString != m_pLastUserString)
  2437.     {
  2438.         HX_VECTOR_DELETE(m_pLastUserString);
  2439.         if (pUserString && *pUserString)
  2440.         {
  2441.             m_pLastUserString = new char[strlen(pUserString) + 1];
  2442.             ::strcpy(m_pLastUserString, pUserString); /* Flawfinder: ignore */
  2443.         }
  2444.     }
  2445.     if (pMoreInfoURL != m_pLastMoreInfoURL)
  2446.     {
  2447.         HX_VECTOR_DELETE(m_pLastMoreInfoURL);
  2448.         if (pMoreInfoURL && *pMoreInfoURL)
  2449.         {
  2450.             m_pLastMoreInfoURL = new char[strlen(pMoreInfoURL) + 1];
  2451.             ::strcpy(m_pLastMoreInfoURL, pMoreInfoURL); /* Flawfinder: ignore */
  2452.         }
  2453.     }
  2454.     m_bIsDone                   = TRUE;
  2455.     m_bIsPresentationClosedToBeSent = TRUE;
  2456.     m_pAudioPlayer->DonePlayback();
  2457.     return HXR_OK;
  2458. }
  2459. HX_RESULT
  2460. HXPlayer::ActualReport
  2461. (
  2462.     const UINT8 unSeverity,
  2463.     HX_RESULT   ulHXCode,
  2464.     const ULONG32       ulUserCode,
  2465.     const char* pUserString,
  2466.     const char* pMoreInfoURL
  2467. )
  2468. {
  2469. #if defined(HELIX_FEATURE_SINKCONTROL)
  2470.     if (m_pErrorSinkControl)
  2471.     {
  2472.         m_pErrorSinkControl->ErrorOccurred(unSeverity, ulHXCode,
  2473.                                            ulUserCode, pUserString,
  2474.                                            pMoreInfoURL);
  2475.     }
  2476. #endif /* HELIX_FEATURE_SINKCONTROL */
  2477.     return HXR_OK;
  2478. }
  2479. STDMETHODIMP_ (IHXBuffer*)
  2480. HXPlayer::GetErrorText(HX_RESULT ulHXCode)
  2481. {
  2482. #if defined(HELIX_FEATURE_RESOURCEMGR)
  2483.     return m_pEngine->GetResMgr()->GetErrorString(ulHXCode);
  2484. #else
  2485.     return NULL;
  2486. #endif /* HELIX_FEATURE_RESOURCEMGR */
  2487. }
  2488. /************************************************************************
  2489.  *  Method:
  2490.  *      IHXAudioPlayerResponse::OnTimeSync
  2491.  *  Purpose:
  2492.  *      Notification interface provided by users of the IHXAudioPlayer
  2493.  *      interface. This method is called by the IHXAudioPlayer when
  2494.  *      audio playback occurs.
  2495.  */
  2496. STDMETHODIMP HXPlayer::OnTimeSync(ULONG32 /*IN*/ ulCurrentTime)
  2497. {
  2498.     HX_RESULT theErr = HXR_OK;
  2499.     CHXMapPtrToPtr::Iterator ndxSource;
  2500.     m_bCurrentPresentationClosed = FALSE;
  2501.     if (!m_bInitialized)
  2502.         return HXR_NOT_INITIALIZED;
  2503.     m_bTimeSyncLocked = TRUE;
  2504.     UpdateCurrentPlayTime( ulCurrentTime );
  2505.     if (m_bIsFirstTimeSync)
  2506.     {
  2507.         m_bIsFirstTimeSync  = FALSE;
  2508.         m_ulFirstTimeSync   = m_ulCurrentPlayTime;
  2509.     }
  2510.     //  dfprintf("buff", "OnTimesync: %lu %lu %lun", HX_GET_TICKCOUNT(), m_ulCurrentPlayTime, m_ulCurrentSystemPlayTime);
  2511.     theErr  = ProcessIdle();
  2512.     m_pCoreMutex->Lock();
  2513.     if (m_bCurrentPresentationClosed)
  2514.     {
  2515.         goto exit;
  2516.     }
  2517. #if defined(HELIX_FEATURE_NESTEDMETA)
  2518.     m_pPersistentComponentManager->OnTimeSync(m_ulCurrentPlayTime);
  2519. #endif /* HELIX_FEATURE_NESTEDMETA */
  2520.     ndxSource = m_pSourceMap->Begin();
  2521.     for (; !theErr && ndxSource != m_pSourceMap->End(); ++ndxSource)
  2522.     {
  2523.         SourceInfo* pSourceInfo = (SourceInfo *)(*ndxSource);
  2524.         pSourceInfo->OnTimeSync(m_ulCurrentPlayTime);
  2525.         if (pSourceInfo->m_pPeerSourceInfo &&
  2526.             pSourceInfo->m_pPeerSourceInfo->IsInitialized())
  2527.         {
  2528.             pSourceInfo->m_pPeerSourceInfo->OnTimeSync(m_ulCurrentPlayTime);
  2529.         }
  2530.         if (m_bCurrentPresentationClosed)
  2531.         {
  2532.             goto exit;
  2533.         }
  2534.     }
  2535.     if (m_BufferingReason == BUFFERING_SEEK || m_BufferingReason == BUFFERING_LIVE_PAUSE)
  2536.     {
  2537.         m_BufferingReason   = BUFFERING_CONGESTION;
  2538.         if (m_pAdviseSink)
  2539.         {
  2540.             m_pAdviseSink->OnPostSeek(m_ulTimeBeforeSeek, m_ulTimeAfterSeek);
  2541.         }
  2542.     }
  2543.     if (m_pAdviseSink)
  2544.     {
  2545.         m_pAdviseSink->OnPosLength( (m_bIsLive ||
  2546.                                     m_ulCurrentPlayTime <= m_ulPresentationDuration) ?
  2547.                                     m_ulCurrentPlayTime : m_ulPresentationDuration,
  2548.                                     m_ulPresentationDuration);
  2549.     }
  2550.     m_bTimeSyncLocked = FALSE;
  2551. exit:
  2552.     m_pCoreMutex->Unlock();
  2553.     return theErr;
  2554. }
  2555. HX_RESULT   HXPlayer::DoURLOpen(CHXURL* pCHXURL, char* pMimeType)
  2556. {
  2557.     HX_RESULT       theErr = HXR_OK;
  2558.     char*           pAltURL = NULL;
  2559.     if (!pCHXURL)
  2560.     {
  2561.         return HXR_UNEXPECTED;
  2562.     }
  2563.     char* pURL = (char*) pCHXURL->GetURL();
  2564.     if (!pURL || !*pURL)
  2565.     {
  2566.         return HXR_UNEXPECTED;
  2567.     }
  2568.     ResetError();
  2569.     ResetRedirectList();
  2570.     m_bCoreLocked = TRUE;
  2571.     m_pCoreMutex->Lock();
  2572. #ifdef _RAHULDEBUG
  2573.     CHXURL::TestCompressURL(); // in chxurl.h
  2574. #endif
  2575.     /* Validate the URL */
  2576.     theErr = pCHXURL->GetLastError();
  2577.     if (theErr)
  2578.     {
  2579.         goto exit;
  2580.     }
  2581.     /* If we are not in a STOP state, do an internal stop */
  2582.     if (!m_bIsPresentationDone)
  2583.     {
  2584. //      m_bIsPresentationClosedToBeSent = FALSE;
  2585.         StopPlayer(END_STOP);
  2586.     }
  2587.     m_bIsDone   = FALSE;
  2588.     m_bIsPresentationDone = FALSE;
  2589.     m_bIsPresentationClosedToBeSent = TRUE;
  2590. #if defined(HELIX_FEATURE_AUTOUPGRADE)
  2591.     HX_RELEASE (m_pUpgradeCollection);
  2592.     m_pUpgradeCollection = new HXUpgradeCollection;
  2593.     m_pUpgradeCollection->AddRef();
  2594. #endif /* HELIX_FEATURE_AUTOUPGRADE */
  2595. #if defined(HELIX_FEATURE_RECORDCONTROL)
  2596.     m_bRecordServiceEnabled = IsRecordServiceEnabled();
  2597. #endif
  2598.     // all presentation started with one track in a group
  2599.     theErr = SetSingleURLPresentation(pCHXURL);
  2600.     if (m_LastError && !theErr)
  2601.     {
  2602.         theErr = m_LastError;
  2603.     }
  2604.     if (theErr)
  2605.     {
  2606.         m_bIsPresentationClosedToBeSent = FALSE;
  2607.         ResetPlayer();
  2608. #if defined(HELIX_FEATURE_VIDEO)
  2609.         /*
  2610.          * Let the site supplier know that we are done changing the layout.
  2611.          */
  2612.         if (m_pSiteSupplier && !m_bBeginChangeLayoutTobeCalled)
  2613.         {
  2614.             m_bBeginChangeLayoutTobeCalled      = TRUE;
  2615.             m_pSiteSupplier->DoneChangeLayout();
  2616.         }
  2617. #endif /* HELIX_FEATURE_VIDEO */
  2618.     }
  2619.     if (!theErr)
  2620.     {
  2621.         SchedulePlayer();
  2622.     }
  2623. exit:
  2624.     if (theErr)
  2625.     {
  2626.         /* If no one has set the last error and there is no user string,
  2627.          * copy URL to the user string
  2628.          */
  2629.         if (!m_LastError && !m_pLastUserString && pURL)
  2630.         {
  2631.             m_pLastUserString = new char[strlen(pURL) + 1];
  2632.             strcpy(m_pLastUserString, pURL); /* Flawfinder: ignore */
  2633.         }
  2634.         SetLastError(theErr);
  2635.     }
  2636.     if (m_LastError)
  2637.     {
  2638.         /* Schedule a ProcessIdle callback. That is where the error
  2639.          * would be reported/ auto-upgrade will be requested.
  2640.          */
  2641.         m_bIsDone = FALSE;
  2642.         SchedulePlayer();
  2643.         m_bIsDone = TRUE;
  2644.         theErr = HXR_OK;
  2645.     }
  2646.     else
  2647.     {
  2648.         if (!m_bPlayStateNotified && m_pEngine)
  2649.         {
  2650.             m_bPlayStateNotified = TRUE;
  2651.             m_pEngine->NotifyPlayState(m_bPlayStateNotified);
  2652.         }
  2653.     }
  2654.     m_pCoreMutex->Unlock();
  2655.     m_bCoreLocked = FALSE;
  2656.     return (theErr);
  2657. }
  2658. /************************************************************************
  2659.  *  Method:
  2660.  *      IHXPlayer::OpenURL
  2661.  *  Purpose:
  2662.  *      Tell the player to open and URL.
  2663.  */
  2664. STDMETHODIMP HXPlayer::OpenURL(const char* pURL)
  2665. {
  2666.     // we want to protect against the TLC opening another URL
  2667.     if (m_bSetModal)
  2668.     {
  2669.         return HXR_OK;
  2670.     }
  2671.     HX_RESULT   hr = HXR_OK;
  2672.     HX_RELEASE(m_pRequest);
  2673.     // get the compresses URL
  2674.     CHXURL url(pURL);
  2675.     pURL = url.GetURL();
  2676.     m_pRequest = new CHXRequest();
  2677.     if( m_pRequest )
  2678.     {
  2679.         m_pRequest->AddRef();
  2680.         m_pRequest->SetURL(url.GetURL());
  2681.         m_bActiveRequest = TRUE;
  2682.         if (m_pClientRequestSink)
  2683.         {
  2684.             m_pClientRequestSink->OnNewRequest(m_pRequest);
  2685.         }
  2686.         hr = DoURLOpen(&url, NULL);
  2687.     }
  2688.     else
  2689.     {
  2690.         hr = HXR_OUTOFMEMORY;
  2691.     }
  2692.     return hr;
  2693. }
  2694. /************************************************************************
  2695.  *      Method:
  2696.  *          IID_IHXPlayer2::OpenRequest
  2697.  *      Purpose:
  2698.  *          Call this method to open the IHXRequest
  2699.  */
  2700. STDMETHODIMP HXPlayer::OpenRequest(IHXRequest* pRequest)
  2701. {
  2702.     // we want to protect against the TLC opening another URL
  2703.     if (m_bSetModal)
  2704.     {
  2705.         return HXR_OK;
  2706.     }
  2707.     HX_RESULT   hr = HXR_OK;
  2708.     const char* pURL = NULL;
  2709.     if (!pRequest)
  2710.     {
  2711.         return HXR_UNEXPECTED;
  2712.     }
  2713.     HX_RELEASE(m_pRequest);
  2714.     m_pRequest = pRequest;
  2715.     m_pRequest->AddRef();
  2716.     m_bActiveRequest = TRUE;
  2717.     // retrieve the URL
  2718.     if (HXR_OK != m_pRequest->GetURL(pURL))
  2719.     {
  2720.         return HXR_UNEXPECTED;
  2721.     }
  2722.     if (m_pClientRequestSink && m_pRequest)
  2723.     {
  2724.         m_pClientRequestSink->OnNewRequest(m_pRequest);
  2725.     }
  2726.     // get the compresses URL
  2727.     CHXURL url(pURL);
  2728.     pURL = url.GetURL();
  2729.     m_pRequest->SetURL(pURL);
  2730.     hr = DoURLOpen(&url, NULL);
  2731.     return hr;
  2732. }
  2733. /************************************************************************
  2734.  *     Method:
  2735.  *         IID_IHXPlayer2::GetRequest
  2736.  *     Purpose:
  2737.  *         Call this method to get the IHXRequest
  2738.  */
  2739. STDMETHODIMP HXPlayer::GetRequest(REF(IHXRequest*) pRequest)
  2740. {
  2741.     HX_RESULT  hr = HXR_OK;
  2742.     pRequest = NULL;
  2743.     if (!m_pRequest)
  2744.     {
  2745.         hr = HXR_UNEXPECTED;
  2746.         goto cleanup;
  2747.     }
  2748.     pRequest = m_pRequest;
  2749.     pRequest->AddRef();
  2750. cleanup:
  2751.     return hr;
  2752. }
  2753. ////////////////////////////
  2754. //
  2755. HX_RESULT
  2756. HXPlayer::SetSingleURLPresentation(const CHXURL* pURL)
  2757. {
  2758.     HX_RESULT   theErr = HXR_OK;
  2759.     SourceInfo* pSourceInfo = NULL;
  2760.     IHXGroup*   pGroup = NULL;
  2761.     IHXValues*  pProperties = NULL;
  2762.     CHXBuffer*  pValue = NULL;
  2763.     m_nGroupCount = 0;
  2764. #if defined(HELIX_FEATURE_BASICGROUPMGR)
  2765.     // create group
  2766.     m_pGroupManager->CreateGroup(pGroup);
  2767.     // create track
  2768.     pProperties = new CHXHeader;
  2769.     pProperties->AddRef();
  2770.     pValue = new CHXBuffer();
  2771.     pValue->AddRef();
  2772.     char* url = (char*)pURL->GetEscapedURL();
  2773.     pValue->Set((BYTE*)url, strlen(url)+1);
  2774.     pProperties->SetPropertyCString("url", pValue);
  2775.     pGroup->AddTrack(pProperties);
  2776.     m_pGroupManager->AddGroup(pGroup);
  2777.     HX_RELEASE(pValue);
  2778.     HX_RELEASE(pProperties);
  2779.     HX_RELEASE(pGroup);