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

Symbian

开发平台:

C/C++

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