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

Symbian

开发平台:

Visual C++

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