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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: sinkctl.cpp,v 1.6.8.1 2004/07/09 02:05:58 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include "hxtypes.h"
  51. #include "hxclsnk.h"
  52. #include "hxengin.h"
  53. #include "hxcore.h"
  54. #include "hxengin.h"
  55. #include "hxsched.h"
  56. #include "hxerror.h"
  57. #include "hxslist.h"
  58. #include "hxcbobj.h"
  59. #include "sinkctl.h"
  60. #include "hxheap.h"
  61. #ifdef _DEBUG
  62. #undef HX_THIS_FILE
  63. static const char HX_THIS_FILE[] = __FILE__;
  64. #endif
  65. CHXAdviseSinkControl::PlayerAdviseSink::PlayerAdviseSink(
  66.     IHXClientAdviseSink* pAdviseSink,
  67.     BOOL bInterruptSafe)
  68. {
  69.     m_pAdviseSink     = pAdviseSink;
  70.     m_pAdviseSink->AddRef();
  71.     m_bInterruptSafe     = bInterruptSafe;
  72.     m_pPendingAdviseList    = NULL;
  73. }
  74. CHXAdviseSinkControl::PlayerAdviseSink::~PlayerAdviseSink()
  75. {
  76.     while (m_pPendingAdviseList && m_pPendingAdviseList->GetCount() > 0)
  77.     {
  78. PendingAdvise* pPendingAdvise = 
  79.     (PendingAdvise*) m_pPendingAdviseList->RemoveHead();
  80. delete pPendingAdvise;
  81.     }
  82.     HX_RELEASE(m_pAdviseSink);
  83.     HX_DELETE(m_pPendingAdviseList);
  84. }
  85. CHXAdviseSinkControl::CHXAdviseSinkControl()
  86.     : m_lRefCount(0) 
  87.     , m_pInterruptState(NULL)
  88. {
  89.     m_pCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)AdviseSinkCallback);
  90.     m_pCallback->AddRef();
  91. }
  92. CHXAdviseSinkControl::~CHXAdviseSinkControl()
  93. {
  94.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  95.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  96.     {
  97. PlayerAdviseSink* pPlayerAdviseSink = 
  98.     (PlayerAdviseSink*) (*lSinkerator);
  99.      HX_DELETE(pPlayerAdviseSink);
  100.     }
  101.     m_pSinkList.RemoveAll();
  102.     HX_RELEASE(m_pInterruptState);
  103.     if (m_pCallback && m_pScheduler)
  104.     {
  105.         m_pScheduler->Remove(m_pCallback->GetPendingCallback());
  106.         m_pCallback->CallbackCanceled();
  107.     }
  108.     HX_RELEASE(m_pCallback);
  109.     HX_RELEASE(m_pScheduler);
  110. }
  111. void
  112. CHXAdviseSinkControl::Init(IHXClientEngine* pEngine)
  113. {
  114.     pEngine->QueryInterface(IID_IHXInterruptState, 
  115. (void**) &m_pInterruptState);
  116.     
  117.     pEngine->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
  118. }
  119. HX_RESULT   
  120. CHXAdviseSinkControl::AddAdviseSink(IHXClientAdviseSink* pAdviseSink)
  121. {
  122.     IHXInterruptSafe* pInterruptSafe =NULL;
  123.     BOOL bInterruptSafe =FALSE;
  124.     pAdviseSink->QueryInterface(IID_IHXInterruptSafe,(void**) &pInterruptSafe);
  125.     if (pInterruptSafe)
  126.     {
  127. bInterruptSafe=pInterruptSafe->IsInterruptSafe();
  128. pInterruptSafe->Release();
  129.     }
  130.     PlayerAdviseSink* pPlayerAdviseSink = new PlayerAdviseSink(pAdviseSink, 
  131. bInterruptSafe);
  132.     m_pSinkList.AddTail(pPlayerAdviseSink);
  133.     return HXR_OK;
  134. }
  135. HX_RESULT   
  136. CHXAdviseSinkControl::RemoveAdviseSink(IHXClientAdviseSink* pAdviseSink)
  137. {
  138.     PlayerAdviseSink* pPlayerAdviseSink;
  139.     CHXSimpleList::Iterator lIterator = m_pSinkList.Begin();
  140.     for (; lIterator != m_pSinkList.End(); ++lIterator)
  141.     {
  142. pPlayerAdviseSink = (PlayerAdviseSink*) (*lIterator);
  143.      if (pPlayerAdviseSink->m_pAdviseSink == pAdviseSink)
  144.      {
  145.     LISTPOSITION pos = m_pSinkList.Find(pPlayerAdviseSink);
  146.     m_pSinkList.RemoveAt(pos);     
  147.     HX_DELETE(pPlayerAdviseSink);
  148.     return HXR_OK;
  149.      }
  150.     }
  151.     return HXR_FAIL;
  152. }
  153. //
  154. // This object is never interrupt safe
  155. // and thus cannot be called at interrupt time.
  156. //
  157. STDMETHODIMP_(BOOL) CHXAdviseSinkControl::IsInterruptSafe()
  158. {
  159. return FALSE;
  160. }
  161. // *** IUnknown methods ***
  162. /////////////////////////////////////////////////////////////////////////
  163. //  Method:
  164. // IUnknown::QueryInterface
  165. //  Purpose:
  166. // Implement this to export the interfaces supported by your 
  167. // object.
  168. //
  169. STDMETHODIMP CHXAdviseSinkControl::QueryInterface(REFIID riid, void** ppvObj)
  170. {
  171.     QInterfaceList qiList[] =
  172.         {
  173.             { GET_IIDHANDLE(IID_IHXClientAdviseSink), (IHXClientAdviseSink*)this },
  174.             { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*)this },
  175.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXClientAdviseSink*)this },
  176.         };
  177.     
  178.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  179. }
  180. /////////////////////////////////////////////////////////////////////////
  181. //  Method:
  182. // IUnknown::AddRef
  183. //  Purpose:
  184. // Everyone usually implements this the same... feel free to use
  185. // this implementation.
  186. //
  187. STDMETHODIMP_(ULONG32) CHXAdviseSinkControl::AddRef()
  188. {
  189.     return InterlockedIncrement(&m_lRefCount);
  190. }
  191. /////////////////////////////////////////////////////////////////////////
  192. //  Method:
  193. // IUnknown::Release
  194. //  Purpose:
  195. // Everyone usually implements this the same... feel free to use
  196. // this implementation.
  197. //
  198. STDMETHODIMP_(ULONG32) CHXAdviseSinkControl::Release()
  199. {
  200.     if (InterlockedDecrement(&m_lRefCount) > 0)
  201.     {
  202.         return m_lRefCount;
  203.     }
  204.     delete this;
  205.     return 0;
  206. }
  207. void
  208. CHXAdviseSinkControl::AddToPendingList(PlayerAdviseSink* pPlayerAdviseSink,
  209.        AdviseType type,
  210.        UINT32 ulArg1, 
  211.        UINT32 ulArg2, 
  212.        char*  pHostName)
  213. {
  214.     if (!pPlayerAdviseSink->m_pPendingAdviseList)
  215.     {
  216. pPlayerAdviseSink->m_pPendingAdviseList = new CHXSimpleList;
  217.     }
  218.     PendingAdvise* pPendingAdvise = new PendingAdvise;
  219.     pPendingAdvise->m_AdviseType = type;
  220.     pPendingAdvise->m_ulArg1 = ulArg1;
  221.     pPendingAdvise->m_ulArg2 = ulArg2;
  222.     if (pHostName)
  223.     {
  224. pPendingAdvise->m_pHostName = new char[strlen(pHostName) + 1];
  225. strcpy(pPendingAdvise->m_pHostName, pHostName); /* Flawfinder: ignore */
  226.     }
  227.     pPlayerAdviseSink->m_pPendingAdviseList->AddTail((void*) pPendingAdvise);
  228.     if (!m_pCallback->GetPendingCallback())
  229.     {
  230.         m_pCallback->CallbackScheduled(m_pScheduler->RelativeEnter(m_pCallback, 0));
  231.     }
  232. }
  233. void
  234. CHXAdviseSinkControl::ProcessAllRequests(void)
  235. {
  236.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  237.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  238.     {
  239. PlayerAdviseSink* pPlayerAdviseSink = 
  240.     (PlayerAdviseSink*) (*lSinkerator);
  241. ProcessPendingRequests(pPlayerAdviseSink);
  242.     }
  243. }
  244. void
  245. CHXAdviseSinkControl::ProcessPendingRequests(PlayerAdviseSink* 
  246. pPlayerAdviseSink)
  247. {
  248.     while (pPlayerAdviseSink->m_pPendingAdviseList && 
  249.    pPlayerAdviseSink->m_pPendingAdviseList->GetCount() > 0)
  250.     {
  251. PendingAdvise* pPendingAdvise = (PendingAdvise*) 
  252. pPlayerAdviseSink->m_pPendingAdviseList->RemoveHead();
  253. switch(pPendingAdvise->m_AdviseType)
  254. {
  255.     case ONPOSLENGTH:
  256.      pPlayerAdviseSink->m_pAdviseSink->OnPosLength(
  257.     pPendingAdvise->m_ulArg1, 
  258.     pPendingAdvise->m_ulArg2);
  259. break;
  260.     case ONPRESENTATIONOPENED:
  261.      pPlayerAdviseSink->m_pAdviseSink->OnPresentationOpened();
  262. break;
  263.     case ONPRESENTATIONCLOSED:
  264.      pPlayerAdviseSink->m_pAdviseSink->OnPresentationClosed();
  265. break;
  266.     case ONSTATISTICSCHANGED:
  267.      pPlayerAdviseSink->m_pAdviseSink->OnStatisticsChanged();
  268. break;
  269.     case ONPRESEEK:
  270.      pPlayerAdviseSink->m_pAdviseSink->OnPreSeek(
  271.     pPendingAdvise->m_ulArg1, 
  272.     pPendingAdvise->m_ulArg2);
  273. break;
  274.     case ONPOSTSEEK:
  275.      pPlayerAdviseSink->m_pAdviseSink->OnPostSeek(
  276.     pPendingAdvise->m_ulArg1, 
  277.     pPendingAdvise->m_ulArg2);
  278. break;
  279.     case ONSTOP:
  280.      pPlayerAdviseSink->m_pAdviseSink->OnStop();
  281. break;
  282.     case ONPAUSE:
  283.          pPlayerAdviseSink->m_pAdviseSink->OnPause(
  284. pPendingAdvise->m_ulArg1);
  285. break;
  286.     case ONBEGIN:
  287.          pPlayerAdviseSink->m_pAdviseSink->OnBegin(
  288. pPendingAdvise->m_ulArg1);
  289. break;
  290.     case ONBUFFERING:
  291.      pPlayerAdviseSink->m_pAdviseSink->OnBuffering(
  292. pPendingAdvise->m_ulArg1, 
  293.        (UINT16) pPendingAdvise->m_ulArg2);
  294. break;
  295.     case ONCONTACTING:
  296.      pPlayerAdviseSink->m_pAdviseSink->OnContacting(
  297.      pPendingAdvise->m_pHostName);
  298. break;
  299.     default:
  300. HX_ASSERT(FALSE);
  301. break;
  302. }
  303. delete pPendingAdvise;
  304.     }
  305. }
  306. /*
  307.  * IHXClientAdviseSink methods
  308.  */
  309. /************************************************************************
  310.  * Method:
  311.  *     IHXClientAdviseSink::OnPosLength
  312.  * Purpose:
  313.  *     Called to advise the client that the position or length of the
  314.  *     current playback context has changed.
  315.  */
  316. STDMETHODIMP
  317. CHXAdviseSinkControl::OnPosLength(UINT32   ulPosition,
  318.    UINT32   ulLength)
  319. {
  320.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  321.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  322.     {
  323. PlayerAdviseSink* pPlayerAdviseSink = 
  324.     (PlayerAdviseSink*) (*lSinkerator);
  325. if (!m_pInterruptState->AtInterruptTime() || 
  326.     pPlayerAdviseSink->m_bInterruptSafe)
  327. {
  328.     ProcessPendingRequests(pPlayerAdviseSink);
  329.          pPlayerAdviseSink->m_pAdviseSink->OnPosLength(ulPosition, 
  330.   ulLength);
  331. }
  332. else
  333. {
  334.     AddToPendingList(pPlayerAdviseSink, ONPOSLENGTH, 
  335.      ulPosition, ulLength);
  336. }
  337.     }
  338.     return HXR_OK;
  339. }
  340. /************************************************************************
  341.  * Method:
  342.  *     IHXClientAdviseSink::OnPresentationOpened
  343.  * Purpose:
  344.  *     Called to advise the client a presentation has been opened.
  345.  */
  346. STDMETHODIMP CHXAdviseSinkControl::OnPresentationOpened()
  347. {
  348.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  349.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  350.     {
  351. PlayerAdviseSink* pPlayerAdviseSink = 
  352.     (PlayerAdviseSink*) (*lSinkerator);
  353. if (!m_pInterruptState->AtInterruptTime() || 
  354.     pPlayerAdviseSink->m_bInterruptSafe)
  355. {
  356.     ProcessPendingRequests(pPlayerAdviseSink);
  357.          pPlayerAdviseSink->m_pAdviseSink->OnPresentationOpened();
  358. }
  359. else
  360. {
  361.     AddToPendingList(pPlayerAdviseSink, ONPRESENTATIONOPENED);
  362. }
  363.     }
  364.     return HXR_OK;
  365. }
  366. /************************************************************************
  367.  * Method:
  368.  *     IHXClientAdviseSink::OnPresentationClosed
  369.  * Purpose:
  370.  *     Called to advise the client a presentation has been closed.
  371.  */
  372. STDMETHODIMP CHXAdviseSinkControl::OnPresentationClosed()
  373. {
  374.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  375.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  376.     {
  377. PlayerAdviseSink* pPlayerAdviseSink = 
  378.     (PlayerAdviseSink*) (*lSinkerator);
  379. if (!m_pInterruptState->AtInterruptTime() || 
  380.     pPlayerAdviseSink->m_bInterruptSafe)
  381. {
  382.     ProcessPendingRequests(pPlayerAdviseSink);
  383.          pPlayerAdviseSink->m_pAdviseSink->OnPresentationClosed();
  384. }
  385. else
  386. {
  387.     AddToPendingList(pPlayerAdviseSink, ONPRESENTATIONCLOSED);
  388. }
  389.     }
  390.     return HXR_OK;
  391. }
  392. /************************************************************************
  393.  * Method:
  394.  *     IHXClientAdviseSink::OnStatisticsChanged
  395.  * Purpose:
  396.  *     Called to advise the client that the presentation statistics
  397.  *     have changed. 
  398.  */
  399. STDMETHODIMP CHXAdviseSinkControl::OnStatisticsChanged(void)
  400. {
  401.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  402.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  403.     {
  404. PlayerAdviseSink* pPlayerAdviseSink = 
  405.     (PlayerAdviseSink*) (*lSinkerator);
  406. if (!m_pInterruptState->AtInterruptTime() || 
  407.     pPlayerAdviseSink->m_bInterruptSafe)
  408. {
  409.     ProcessPendingRequests(pPlayerAdviseSink);
  410.          pPlayerAdviseSink->m_pAdviseSink->OnStatisticsChanged();
  411. }
  412. else
  413. {
  414.     AddToPendingList(pPlayerAdviseSink, ONSTATISTICSCHANGED);
  415. }
  416.     }
  417.     return HXR_OK;
  418. }
  419. /************************************************************************
  420.  * Method:
  421.  *     IHXClientAdviseSink::OnPreSeek
  422.  * Purpose:
  423.  *     Called by client engine to inform the client that a seek is
  424.  *     about to occur. The render is informed the last time for the 
  425.  *     stream's time line before the seek, as well as the first new
  426.  *     time for the stream's time line after the seek will be completed.
  427.  *
  428.  */
  429. STDMETHODIMP CHXAdviseSinkControl::OnPreSeek( ULONG32 ulOldTime,
  430. ULONG32 ulNewTime)
  431. {
  432.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  433.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  434.     {
  435. PlayerAdviseSink* pPlayerAdviseSink = 
  436.     (PlayerAdviseSink*) (*lSinkerator);
  437. if (!m_pInterruptState->AtInterruptTime() || 
  438.     pPlayerAdviseSink->m_bInterruptSafe)
  439. {
  440.     ProcessPendingRequests(pPlayerAdviseSink);
  441.          pPlayerAdviseSink->m_pAdviseSink->OnPreSeek(ulOldTime, 
  442. ulNewTime);
  443. }
  444. else
  445. {
  446.     AddToPendingList(pPlayerAdviseSink, ONPRESEEK, 
  447.      ulOldTime, ulNewTime);
  448. }
  449.     }
  450.     return HXR_OK;
  451. }
  452. /************************************************************************
  453.  * Method:
  454.  *     IHXClientAdviseSink::OnPostSeek
  455.  * Purpose:
  456.  *     Called by client engine to inform the client that a seek has
  457.  *     just occured. The render is informed the last time for the 
  458.  *     stream's time line before the seek, as well as the first new
  459.  *     time for the stream's time line after the seek.
  460.  *
  461.  */
  462. STDMETHODIMP CHXAdviseSinkControl::OnPostSeek( ULONG32 ulOldTime,
  463. ULONG32 ulNewTime)
  464. {
  465.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  466.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  467.     {
  468. PlayerAdviseSink* pPlayerAdviseSink = 
  469.     (PlayerAdviseSink*) (*lSinkerator);
  470. if (!m_pInterruptState->AtInterruptTime() || 
  471.     pPlayerAdviseSink->m_bInterruptSafe)
  472. {
  473.     ProcessPendingRequests(pPlayerAdviseSink);
  474.          pPlayerAdviseSink->m_pAdviseSink->OnPostSeek(ulOldTime, 
  475.  ulNewTime);
  476. }
  477. else
  478. {
  479.     AddToPendingList(pPlayerAdviseSink, ONPOSTSEEK, 
  480.      ulOldTime, ulNewTime);
  481. }
  482.     }
  483.     return HXR_OK;
  484. }
  485. /************************************************************************
  486.  * Method:
  487.  *     IHXClientAdviseSink::OnStop
  488.  * Purpose:
  489.  *     Called by client engine to inform the client that a stop has
  490.  *     just occured. 
  491.  *
  492.  */
  493. STDMETHODIMP CHXAdviseSinkControl::OnStop(void)
  494. {
  495.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  496.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  497.     {
  498. PlayerAdviseSink* pPlayerAdviseSink = 
  499.     (PlayerAdviseSink*) (*lSinkerator);
  500. if (!m_pInterruptState->AtInterruptTime() || 
  501.     pPlayerAdviseSink->m_bInterruptSafe)
  502. {
  503.     ProcessPendingRequests(pPlayerAdviseSink);
  504.          pPlayerAdviseSink->m_pAdviseSink->OnStop();
  505. }
  506. else
  507. {
  508.     AddToPendingList(pPlayerAdviseSink, ONSTOP);
  509. }
  510.     }
  511.     return HXR_OK;
  512. }
  513. /************************************************************************
  514.  * Method:
  515.  *     IHXClientAdviseSink::OnPause
  516.  * Purpose:
  517.  *     Called by client engine to inform the client that a pause has
  518.  *     just occured. The render is informed the last time for the 
  519.  *     stream's time line before the pause.
  520.  *
  521.  */
  522. STDMETHODIMP CHXAdviseSinkControl::OnPause(ULONG32 ulTime)
  523. {
  524.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  525.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  526.     {
  527. PlayerAdviseSink* pPlayerAdviseSink = 
  528.     (PlayerAdviseSink*) (*lSinkerator);
  529. if (!m_pInterruptState->AtInterruptTime() || 
  530.     pPlayerAdviseSink->m_bInterruptSafe)
  531. {
  532.     ProcessPendingRequests(pPlayerAdviseSink);
  533.          pPlayerAdviseSink->m_pAdviseSink->OnPause(ulTime);
  534. }
  535. else
  536. {
  537.     AddToPendingList(pPlayerAdviseSink, ONPAUSE, ulTime);
  538. }
  539.     }
  540.     return HXR_OK;
  541. }
  542. /************************************************************************
  543.  * Method:
  544.  *     IHXClientAdviseSink::OnBegin
  545.  * Purpose:
  546.  *     Called by client engine to inform the client that a begin or
  547.  *     resume has just occured. The render is informed the first time 
  548.  *     for the stream's time line after the resume.
  549.  *
  550.  */
  551. STDMETHODIMP CHXAdviseSinkControl::OnBegin(ULONG32 ulTime)
  552. {
  553.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  554.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  555.     {
  556. PlayerAdviseSink* pPlayerAdviseSink = 
  557.     (PlayerAdviseSink*) (*lSinkerator);
  558. if (!m_pInterruptState->AtInterruptTime() || 
  559.     pPlayerAdviseSink->m_bInterruptSafe)
  560. {
  561.     ProcessPendingRequests(pPlayerAdviseSink);
  562.          pPlayerAdviseSink->m_pAdviseSink->OnBegin(ulTime);
  563. }
  564. else
  565. {
  566.     AddToPendingList(pPlayerAdviseSink, ONBEGIN, ulTime);
  567. }
  568.     }
  569.     return HXR_OK;
  570. }
  571. /************************************************************************
  572.  * Method:
  573.  *     IHXClientAdviseSink::OnBuffering
  574.  * Purpose:
  575.  *     Called by client engine to inform the client that buffering
  576.  *     of data is occuring. The render is informed of the reason for
  577.  *     the buffering (start-up of stream, seek has occured, network
  578.  *     congestion, etc.), as well as percentage complete of the 
  579.  *     buffering process.
  580.  *
  581.  */
  582. STDMETHODIMP CHXAdviseSinkControl::OnBuffering(ULONG32 ulFlags,
  583. UINT16 unPercentComplete)
  584. {
  585.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  586.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  587.     {
  588. PlayerAdviseSink* pPlayerAdviseSink = 
  589.     (PlayerAdviseSink*) (*lSinkerator);
  590. if (!m_pInterruptState->AtInterruptTime() || 
  591.     pPlayerAdviseSink->m_bInterruptSafe)
  592. {
  593.     ProcessPendingRequests(pPlayerAdviseSink);
  594.          pPlayerAdviseSink->m_pAdviseSink->OnBuffering(ulFlags, 
  595.   unPercentComplete);
  596. }
  597. else
  598. {
  599.     AddToPendingList(pPlayerAdviseSink, ONBUFFERING, 
  600.      ulFlags, (UINT32) unPercentComplete);
  601. }
  602.     }
  603.     return HXR_OK;
  604. }
  605. /************************************************************************
  606.  * Method:
  607.  *     IHXClientAdviseSink::OnContacting
  608.  * Purpose:
  609.  *     Called by client engine to inform the client is contacting
  610.  *     hosts(s).
  611.  *
  612.  */
  613. STDMETHODIMP CHXAdviseSinkControl::OnContacting(const char* pHostName)
  614. {
  615.     CHXSimpleList::Iterator lSinkerator = m_pSinkList.Begin();
  616.     for (;  lSinkerator != m_pSinkList.End(); ++lSinkerator)
  617.     {
  618. PlayerAdviseSink* pPlayerAdviseSink = 
  619.     (PlayerAdviseSink*) (*lSinkerator);
  620. if (!m_pInterruptState->AtInterruptTime() || 
  621.     pPlayerAdviseSink->m_bInterruptSafe)
  622. {
  623.     ProcessPendingRequests(pPlayerAdviseSink);
  624.          pPlayerAdviseSink->m_pAdviseSink->OnContacting(pHostName);
  625. }
  626. else
  627. {
  628.     AddToPendingList(pPlayerAdviseSink, ONCONTACTING, 
  629.      0, 0, (char*) pHostName);
  630. }
  631.     }
  632.     return HXR_OK;
  633. }
  634. void CHXAdviseSinkControl::AdviseSinkCallback(void* pParam)
  635. {
  636.     CHXAdviseSinkControl* pObj = (CHXAdviseSinkControl*)pParam;
  637.     
  638.     if (pObj)
  639.     {
  640.         pObj->ProcessAllRequests();
  641.     }
  642. }    
  643. /************************************************************************
  644. /* CHXErrorSinkControl */
  645. CHXErrorSinkControl::CHXErrorSinkControl() :
  646.      m_lRefCount (0)
  647.     ,m_pPendingErrorList(NULL) 
  648.     ,m_pInterruptState(NULL)
  649.     ,m_pScheduler(NULL)
  650.     ,m_pErrorCallback(NULL)
  651. {
  652.     m_pErrorCallback = new CHXGenericCallback((void*)this, (fGenericCBFunc)ErrorCallback);
  653.     m_pErrorCallback->AddRef();
  654. }
  655. CHXErrorSinkControl::~CHXErrorSinkControl()
  656. {
  657.     Close();
  658. }
  659. STDMETHODIMP
  660. CHXErrorSinkControl::AddErrorSink (
  661. IHXErrorSink* pErrorSink,
  662.                                 const UINT8     unLowSeverity,
  663.                                 const UINT8     unHighSeverity)
  664. {
  665.     if (pErrorSink)
  666.     {
  667.      PlayerErrorSink* pPlayerErrorSink = new PlayerErrorSink(pErrorSink, unLowSeverity, unHighSeverity);
  668.      m_pSinkList.AddTail(pPlayerErrorSink);
  669.      pErrorSink->AddRef();
  670.     
  671.     }
  672.     return HXR_OK;
  673. }
  674. STDMETHODIMP
  675. CHXErrorSinkControl::RemoveErrorSink(IHXErrorSink* pErrorSink)
  676. {
  677.     PlayerErrorSink* pPlayerErrorSink;
  678.     CHXSimpleList::Iterator lIterator = m_pSinkList.Begin();
  679.     for (; lIterator != m_pSinkList.End(); ++lIterator)
  680.     {
  681. pPlayerErrorSink = (PlayerErrorSink *) (*lIterator);
  682.      if (pPlayerErrorSink->m_pErrorSink == pErrorSink)
  683.      {
  684.     HX_RELEASE (pErrorSink);
  685.     
  686.     LISTPOSITION pos = m_pSinkList.Find(pPlayerErrorSink);
  687.     m_pSinkList.RemoveAt(pos);     
  688.     delete pPlayerErrorSink;
  689.     return HXR_OK;
  690.      }
  691.     }
  692.     return HXR_FAIL;
  693. }
  694. STDMETHODIMP 
  695. CHXErrorSinkControl::QueryInterface(REFIID riid, void** ppvObj)
  696. {
  697.     QInterfaceList qiList[] =
  698.         {
  699.             { GET_IIDHANDLE(IID_IHXErrorSinkControl), (IHXErrorSinkControl*)this },
  700.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXErrorSinkControl*)this },
  701.         };
  702.     
  703.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  704. }
  705. STDMETHODIMP_ (ULONG32) 
  706. CHXErrorSinkControl::AddRef()
  707. {
  708.     return InterlockedIncrement(&m_lRefCount);
  709. }
  710. STDMETHODIMP_ (ULONG32) 
  711. CHXErrorSinkControl::Release()
  712. {
  713.     if (InterlockedDecrement(&m_lRefCount) > 0)
  714.     {
  715. return m_lRefCount;
  716.     }
  717.     delete this;
  718.     return 0;
  719. }
  720. void 
  721. CHXErrorSinkControl::GetSeverityRange(IHXErrorSink* pErrorSink, 
  722. UINT8& unLowSeverity, 
  723.      UINT8& unHighSeverity)
  724. {
  725.     PlayerErrorSink* pPlayerErrorSink;
  726.     CHXSimpleList::Iterator lIterator = m_pSinkList.Begin();
  727.     for (; lIterator != m_pSinkList.End(); ++lIterator)
  728.     {
  729. pPlayerErrorSink = (PlayerErrorSink *) (*lIterator);
  730.      if (pPlayerErrorSink->m_pErrorSink == pErrorSink)
  731.      {
  732.     unLowSeverity = pPlayerErrorSink->m_unLowSeverity;
  733.     unHighSeverity = pPlayerErrorSink->m_unHighSeverity;
  734.     break;
  735.      }
  736.     }
  737. }
  738. void
  739. CHXErrorSinkControl::Init(IHXClientEngine* pEngine)
  740. {
  741.     pEngine->QueryInterface(IID_IHXInterruptState, 
  742. (void**) &m_pInterruptState);
  743.     
  744.     pEngine->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
  745. }
  746. void 
  747. CHXErrorSinkControl::Close()
  748. {
  749.     PlayerErrorSink* pPlayerErrorSink;
  750.     CHXSimpleList::Iterator lIterator = m_pSinkList.Begin();
  751.     for (; lIterator != m_pSinkList.End(); ++lIterator)
  752.     {
  753. pPlayerErrorSink = (PlayerErrorSink *) (*lIterator);
  754. HX_RELEASE (pPlayerErrorSink->m_pErrorSink);
  755. delete pPlayerErrorSink;
  756.     }
  757.     m_pSinkList.RemoveAll();
  758.     while (m_pPendingErrorList && m_pPendingErrorList->GetCount() > 0)
  759.     {
  760. ErrorReport* pErrorReport = 
  761.     (ErrorReport*) m_pPendingErrorList->RemoveHead();
  762. delete pErrorReport;
  763.     }
  764.     
  765.     if (m_pErrorCallback)
  766.     {
  767.         m_pScheduler->Remove(m_pErrorCallback->GetPendingCallback());
  768.         m_pErrorCallback->CallbackCanceled();
  769.         HX_RELEASE(m_pErrorCallback);
  770.     }
  771.     HX_DELETE(m_pPendingErrorList);
  772.     HX_RELEASE(m_pInterruptState);
  773.     HX_RELEASE(m_pScheduler);
  774. }
  775. HX_RESULT 
  776. CHXErrorSinkControl::ErrorOccurred( const UINT8 unSeverity,  
  777.     const ULONG32 ulHXCode,
  778.     const ULONG32 ulUserCode,
  779.     const char* pUserString,
  780.     const char* pMoreInfoURL)
  781. {
  782.     if (m_pInterruptState->AtInterruptTime())
  783.     {
  784. if (!m_pPendingErrorList)
  785. {
  786.     m_pPendingErrorList = new CHXSimpleList;
  787. }
  788. ErrorReport* pErrorReport = new ErrorReport;
  789. pErrorReport->m_unSeverity = unSeverity;
  790. pErrorReport->m_ulHXCode = ulHXCode;
  791. pErrorReport->m_ulUserCode = ulUserCode;
  792. if (pUserString && *pUserString)
  793. {
  794.     pErrorReport->m_pUserString = new char[strlen(pUserString) + 1];
  795.     ::strcpy(pErrorReport->m_pUserString, pUserString); /* Flawfinder: ignore */
  796. }
  797. if (pMoreInfoURL && *pMoreInfoURL)
  798. {
  799.     pErrorReport->m_pMoreInfoURL = new char[strlen(pMoreInfoURL) + 1];
  800.     ::strcpy(pErrorReport->m_pMoreInfoURL, pMoreInfoURL); /* Flawfinder: ignore */
  801. }
  802. m_pPendingErrorList->AddTail((void*) pErrorReport);
  803.         if (!m_pErrorCallback->GetPendingCallback())
  804. {
  805.             m_pErrorCallback->CallbackScheduled(
  806.              m_pScheduler->RelativeEnter(m_pErrorCallback, 0));
  807. }
  808. return HXR_OK;
  809.     }
  810.     ReportPendingErrors();
  811.     CallReport(unSeverity,
  812.        ulHXCode,
  813.        ulUserCode,
  814.        pUserString,
  815.        pMoreInfoURL);
  816.     return HXR_OK;
  817. }
  818. void
  819. CHXErrorSinkControl::ReportPendingErrors()
  820. {
  821.     if (m_pErrorCallback)
  822.     {
  823.         m_pScheduler->Remove(m_pErrorCallback->GetPendingCallback());
  824.         m_pErrorCallback->CallbackCanceled();
  825.     }
  826.     while (m_pPendingErrorList && m_pPendingErrorList->GetCount() > 0)
  827.     {
  828. ErrorReport* pErrorReport = 
  829.     (ErrorReport*) m_pPendingErrorList->RemoveHead();
  830. CallReport(pErrorReport->m_unSeverity,
  831.    pErrorReport->m_ulHXCode,
  832.    pErrorReport->m_ulUserCode,
  833.    pErrorReport->m_pUserString,
  834.    pErrorReport->m_pMoreInfoURL);
  835. delete pErrorReport;
  836.     }
  837. }
  838. HX_RESULT
  839. CHXErrorSinkControl::CallReport
  840. (
  841.     const UINT8 unSeverity,  
  842.     HX_RESULT ulHXCode,
  843.     const ULONG32 ulUserCode,
  844.     const char* pUserString,
  845.     const char* pMoreInfoURL
  846. )
  847. {
  848.     CHXSimpleList::Iterator ndxSink;
  849.     for (ndxSink = m_pSinkList.Begin(); 
  850.  ndxSink != m_pSinkList.End(); ++ndxSink)
  851.     {
  852. PlayerErrorSink* pPlayerErrorSink =
  853. (PlayerErrorSink*) (*ndxSink);
  854. // error-reporting based on its severity   
  855. if (unSeverity >= pPlayerErrorSink->m_unLowSeverity &&
  856.     unSeverity <= pPlayerErrorSink->m_unHighSeverity)
  857. //     unSeverity <= pPlayerErrorSink->m_unHighSeverity && !m_pAltURLs->GetCount())
  858. {
  859.     pPlayerErrorSink->m_pErrorSink->ErrorOccurred(unSeverity, ulHXCode,
  860. ulUserCode, pUserString, pMoreInfoURL);
  861. }
  862.     }
  863.     return HXR_OK;
  864. }
  865. void CHXErrorSinkControl::ErrorCallback(void* pParam)
  866. {
  867.     CHXErrorSinkControl* pObj = (CHXErrorSinkControl*)pParam;
  868.     if (pObj)
  869.     {
  870.         pObj->ReportPendingErrors();
  871.     }
  872. }