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

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. // system
  36. #include <stdio.h>
  37. // include
  38. #include "hxcom.h"
  39. #include "hxtypes.h"
  40. #include "hxcomm.h"
  41. #include "ihxpckts.h"
  42. #include "hxfiles.h"
  43. #include "hxformt.h"
  44. #include "hxplugn.h"
  45. #include "hxver.h"
  46. // pnmisc
  47. #include "baseobj.h"
  48. // pxcomlib
  49. #include "buffutil.h"
  50. // brushff
  51. #include "brushff.h"
  52. #include "brushff.ver"
  53. // pndebug
  54. #include "errdbg.h"
  55. #include "hxheap.h"
  56. #ifdef _DEBUG
  57. #undef HX_THIS_FILE             
  58. static const char HX_THIS_FILE[] = __FILE__;
  59. #endif
  60. const char* const CBrushFileFormat::m_pszDescription       = "RealNetworks Brush File Format Plugin";
  61. const char* const CBrushFileFormat::m_pszCopyright         = HXVER_COPYRIGHT;
  62. const char* const CBrushFileFormat::m_pszMoreInfoURL       = HXVER_MOREINFO;
  63. const char* const CBrushFileFormat::m_ppszFileMimeTypes[]  = {"text/brush", NULL};
  64. const char* const CBrushFileFormat::m_ppszFileExtensions[] = {"bsh", NULL};
  65. const char* const CBrushFileFormat::m_ppszFileOpenNames[]  = {"Brush Files (*.bsh)", NULL};
  66. const char* const CBrushFileFormat::m_pszStreamMimeType    = "application/vnd.rn-brushstream";
  67. const UINT32      CBrushFileFormat::m_ulContentVersion     = HX_ENCODE_PROD_VERSION(0, 0, 0, 0);
  68. const UINT32      CBrushFileFormat::m_ulStreamVersion      = HX_ENCODE_PROD_VERSION(0, 0, 0, 0);
  69. CBrushFileFormat::CBrushFileFormat()
  70. {
  71.     m_lRefCount = 0;
  72.     Reset();
  73. };
  74. CBrushFileFormat::~CBrushFileFormat()
  75. {
  76.     Deallocate();
  77. };
  78. STDMETHODIMP CBrushFileFormat::QueryInterface(REFIID riid, void** ppvObj)
  79. {
  80.     HX_RESULT retVal = HXR_OK;
  81.     if (IsEqualIID(riid, IID_IUnknown))
  82.     {
  83.         AddRef();
  84.         *ppvObj = (IUnknown*) (IHXPlugin*) this;
  85.     }
  86.     else if (IsEqualIID(riid, IID_IHXPlugin))
  87.     {
  88.         AddRef();
  89.         *ppvObj = (IHXPlugin*) this;
  90.     }
  91.     else if (IsEqualIID(riid, IID_IHXFileFormatObject))
  92.     {
  93.         AddRef();
  94.         *ppvObj = (IHXFileFormatObject*) this;
  95.     }
  96.     else if (IsEqualIID(riid, IID_IHXFileResponse))
  97.     {
  98.         AddRef();
  99.         *ppvObj = (IHXFileResponse*) this;
  100.     }
  101.     else
  102.     {
  103.         *ppvObj = NULL;
  104.         retVal  = HXR_NOINTERFACE;
  105.     }
  106.     return retVal;
  107. }
  108. STDMETHODIMP_(UINT32) CBrushFileFormat::AddRef()
  109. {
  110.     return InterlockedIncrement(&m_lRefCount);
  111. }
  112. STDMETHODIMP_(UINT32) CBrushFileFormat::Release()
  113. {
  114.     if (InterlockedDecrement(&m_lRefCount) > 0)
  115.     {
  116.         return m_lRefCount;
  117.     }
  118.     delete this;
  119.     return 0;
  120. }
  121. STDMETHODIMP CBrushFileFormat::GetPluginInfo(REF(BOOL)        rbLoadMultiple,
  122.                                              REF(const char*) rpszDescription,
  123.                                              REF(const char*) rpszCopyright,
  124.                                              REF(const char*) rpszMoreInfoURL,
  125.                                              REF(UINT32)      rulVersionNumber)
  126. {
  127.     rbLoadMultiple   = TRUE;
  128.     rpszDescription  = (const char*) m_pszDescription;
  129.     rpszCopyright    = (const char*) m_pszCopyright;
  130.     rpszMoreInfoURL  = (const char*) m_pszMoreInfoURL;
  131.     rulVersionNumber = TARVER_ULONG32_VERSION;
  132.     return HXR_OK;
  133. }
  134. STDMETHODIMP CBrushFileFormat::InitPlugin(IUnknown* pContext)
  135. {
  136.     HX_RESULT retVal = HXR_FAIL;
  137.     if (pContext)
  138.     {
  139.         // Clear out everything
  140.         Deallocate();
  141.         // Save a copy of the calling context
  142.         m_pContext = pContext;
  143.         m_pContext->AddRef();
  144.         // Get an interface to the common class factory
  145.         retVal = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  146.                                             (void**) &m_pCommonClassFactory);
  147.         if (SUCCEEDED(retVal))
  148.         {
  149.             // Set the state
  150.             m_ulState = kStatePluginInitialized;
  151.         }
  152.     }
  153.     return retVal;
  154. }
  155. STDMETHODIMP CBrushFileFormat::GetFileFormatInfo(REF(const char**) rppszFileMimeTypes,
  156.                                                  REF(const char**) rppszFileExtensions,  
  157.                                                  REF(const char**) rppszFileOpenNames)
  158. {
  159.     rppszFileMimeTypes  = (const char**) m_ppszFileMimeTypes;
  160.     rppszFileExtensions = (const char**) m_ppszFileExtensions;
  161.     rppszFileOpenNames  = (const char**) m_ppszFileOpenNames;
  162.     return HXR_OK;
  163. }
  164. STDMETHODIMP CBrushFileFormat::InitFileFormat(IHXRequest*        pRequest, 
  165.                                               IHXFormatResponse* pFormatResponse,
  166.                                               IHXFileObject*     pFileObject)
  167. {
  168.     HX_RESULT retVal = HXR_OK;
  169.     if (pRequest && pFormatResponse && pFileObject)
  170.     {
  171.         if (m_ulState == kStatePluginInitialized)
  172.         {
  173.             // Find out from the 822 headers if this
  174.             // is a NULL brush
  175.             m_bNullBrush = IsNullBrush(pRequest);
  176.             // Save members
  177.             HX_RELEASE(m_pFormatResponse);
  178.             m_pFormatResponse = pFormatResponse;
  179.             m_pFormatResponse->AddRef();
  180.             HX_RELEASE(m_pFileObject);
  181.             m_pFileObject = pFileObject;
  182.             m_pFileObject->AddRef();
  183.             // Set the state
  184.             m_ulState = kStateFileInitPending;
  185.             // Init the file object
  186.             m_pFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, this);
  187.         }
  188.         else
  189.         {
  190.             retVal = HXR_UNEXPECTED;
  191.         }
  192.     }
  193.     else
  194.     {
  195.         retVal = HXR_FAIL;
  196.     }
  197.     if (FAILED(retVal) && pFormatResponse)
  198.     {
  199.         pFormatResponse->InitDone(retVal);
  200.     }
  201.     return retVal;
  202. }
  203. STDMETHODIMP CBrushFileFormat::GetFileHeader()
  204. {
  205.     HX_RESULT retVal = HXR_OK;
  206.     if (m_ulState == kStateFileFormatInitialized)
  207.     {
  208.         // Get an IHXValues object
  209.         IHXValues* pFileHeader = NULL;
  210.         retVal                  = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues,
  211.                                                                         (void**) &pFileHeader);
  212.         if (SUCCEEDED(retVal))
  213.         {
  214.             // Set the stream count
  215.             pFileHeader->SetPropertyULONG32("StreamCount",    1);
  216.             pFileHeader->SetPropertyULONG32("IsRealDataType", 1);
  217.             // Set the new state
  218.             m_ulState = kStateFileHeaderSent;
  219.             // Call the response interface
  220.             m_pFormatResponse->FileHeaderReady(HXR_OK, pFileHeader);
  221.         }
  222.         HX_RELEASE(pFileHeader);
  223.         if (FAILED(retVal))
  224.         {
  225.             m_pFormatResponse->FileHeaderReady(retVal, NULL);
  226.         }
  227.     }
  228.     else
  229.     {
  230.         retVal = HXR_UNEXPECTED;
  231.     }
  232.     return retVal;
  233. }
  234. STDMETHODIMP CBrushFileFormat::GetStreamHeader(UINT16 usStreamNum)
  235. {
  236.     HX_RESULT retVal = HXR_OK;
  237.     if (m_ulState == kStateFileHeaderSent)
  238.     {
  239.         // Create an IHXValues object
  240.         IHXValues* pStreamHeader = NULL;
  241.         retVal                    = m_pCommonClassFactory->CreateInstance(CLSID_IHXValues,
  242.                                                                           (void**) &pStreamHeader);
  243.         if (SUCCEEDED(retVal))
  244.         {
  245.             // Create mime type IHXBuffer string
  246.             IHXBuffer* pMimeStr = NULL;
  247.             retVal = PXUtilities::CreateStringBuffer((const char*) m_pszStreamMimeType,
  248.                                                      m_pContext,
  249.                                                      pMimeStr);
  250.             if (SUCCEEDED(retVal))
  251.             {
  252.                 // Create intrinsic duration type string buffer
  253.                 IHXBuffer* pIntrin = NULL;
  254.                 retVal = PXUtilities::CreateStringBuffer("intrinsicDurationDiscrete",
  255.                                                          m_pContext,
  256.                                                          pIntrin);
  257.                 if (SUCCEEDED(retVal))
  258.                 {
  259.                     // Create ASM rulebook string buffer
  260.                     char szASM[64]; /* Flawfinder: ignore */
  261.                     sprintf(szASM, "AverageBandwidth=%lu,Priority=5;", kDefaultBitrate); /* Flawfinder: ignore */
  262.                     IHXBuffer* pASM = NULL;
  263.                     retVal = PXUtilities::CreateStringBuffer((const char*) szASM,
  264.                                                              m_pContext, pASM);
  265.                     if (SUCCEEDED(retVal))
  266.                     {
  267.                         // Set the properties
  268.                         pStreamHeader->SetPropertyULONG32("StreamNumber",          0);
  269.                         pStreamHeader->SetPropertyULONG32("MaxBitRate",            kDefaultBitrate);
  270.                         pStreamHeader->SetPropertyULONG32("AvgBitRate",            kDefaultBitrate);
  271.                         pStreamHeader->SetPropertyULONG32("MaxPacketSize",         kDefaultPacketSize);
  272.                         pStreamHeader->SetPropertyULONG32("AvgPacketSize",         kDefaultPacketSize);
  273.                         pStreamHeader->SetPropertyULONG32("Preroll",               kDefaultPreroll);
  274.                         pStreamHeader->SetPropertyULONG32("Duration",              kDefaultDuration);
  275.                         pStreamHeader->SetPropertyCString("MimeType",              pMimeStr);
  276.                         pStreamHeader->SetPropertyULONG32("ContentVersion",        m_ulContentVersion);
  277.                         pStreamHeader->SetPropertyULONG32("StreamVersion",         m_ulStreamVersion);
  278.                         pStreamHeader->SetPropertyCString("ASMRuleBook",           pASM);
  279.                         pStreamHeader->SetPropertyCString("intrinsicDurationType", pIntrin);
  280.                         if (m_pFileBuffer)
  281.                         {
  282.                             pStreamHeader->SetPropertyBuffer("OpaqueData", m_pFileBuffer);
  283.                         }
  284.                         if (m_bNullBrush)
  285.                         {
  286.                             pStreamHeader->SetPropertyULONG32("NullBrush", 1);
  287.                         }
  288.                         // Set the new state
  289.                         m_ulState = kStateReadyForGetPacket;
  290.                         // Pass the stream header back to the server
  291.                         m_pFormatResponse->StreamHeaderReady(HXR_OK, pStreamHeader);
  292.                     }
  293.                     HX_RELEASE(pASM);
  294.                 }
  295.                 HX_RELEASE(pIntrin);
  296.             }
  297.             HX_RELEASE(pMimeStr);
  298.         }
  299.         HX_RELEASE(pStreamHeader);
  300.         // Now we can release the file buffer
  301.         HX_RELEASE(m_pFileBuffer);
  302.     }
  303.     else
  304.     {
  305.         retVal = HXR_UNEXPECTED;
  306.     }
  307.     if (FAILED(retVal))
  308.     {
  309.         m_pFormatResponse->StreamHeaderReady(retVal, NULL);
  310.     }
  311.     return retVal;
  312. }
  313. STDMETHODIMP CBrushFileFormat::GetPacket(UINT16 usStreamNum)
  314. {
  315.     HX_RESULT retVal = HXR_OK;
  316.     if (m_ulState == kStateReadyForGetPacket)
  317.     {
  318.         if (usStreamNum == 0)
  319.         {
  320.             // Set the state
  321.             m_ulState = kStateStreamDoneSent;
  322.             // Read from the file
  323.             m_pFormatResponse->StreamDone(0);
  324.         }
  325.         else
  326.         {
  327.             retVal = HXR_INVALID_PARAMETER;
  328.         }
  329.     }
  330.     else
  331.     {
  332.         retVal = HXR_UNEXPECTED;
  333.     }
  334.     return retVal;
  335. }
  336. STDMETHODIMP CBrushFileFormat::Seek(UINT32 ulOffset)
  337. {
  338.     HX_RESULT retVal = HXR_OK;
  339.     if (m_pFormatResponse)
  340.     {
  341.         // Set the state
  342.         m_ulState = kStateReadyForGetPacket;
  343.         // Tell the format response the seek is done
  344.         m_pFormatResponse->SeekDone(HXR_OK);
  345.     }
  346.     else
  347.     {
  348.         retVal = HXR_UNEXPECTED;
  349.     }
  350.     return retVal;
  351. }
  352. STDMETHODIMP CBrushFileFormat::Close()
  353. {
  354.     HX_RESULT retVal = HXR_OK;
  355.     Deallocate();
  356.     return retVal;
  357. }
  358. STDMETHODIMP CBrushFileFormat::InitDone(HX_RESULT status)
  359. {
  360.     HX_RESULT retVal = HXR_OK;
  361.     if (m_ulState == kStateFileInitPending)
  362.     {
  363.         if (SUCCEEDED(status))
  364.         {
  365.             // Set the new state
  366.             m_ulState = kStateFileReadPending;
  367.             // Read the first kDefaultPacketSize bytes of the file
  368.             m_pFileObject->Read(kDefaultPacketSize);
  369.         }
  370.         else
  371.         {
  372.             // Set the state
  373.             m_ulState = kStateError;
  374.             // Inform the response interface of the error
  375.             m_pFormatResponse->InitDone(status);
  376.         }
  377.     }
  378.     else
  379.     {
  380.         retVal = HXR_UNEXPECTED;
  381.     }
  382.     return retVal;
  383. }
  384. STDMETHODIMP CBrushFileFormat::SeekDone(HX_RESULT status)
  385. {
  386.     return HXR_UNEXPECTED;
  387. }
  388. STDMETHODIMP CBrushFileFormat::ReadDone(HX_RESULT status, IHXBuffer* pBuffer)
  389. {
  390.     HX_RESULT retVal = HXR_OK;
  391.     if (m_ulState == kStateFileReadPending)
  392.     {
  393.         if (SUCCEEDED(status))
  394.         {
  395.             // If we already have a buffer, then we'll need to
  396.             // copy this buffer into the bigger one. In practical
  397.             // use, this should never happen, since the SMIL-generated
  398.             // "brush file" should only be a few bytes, well within
  399.             // kDefaultPacketSize bytes.
  400.             if (m_pFileBuffer)
  401.             {
  402.                 IHXBuffer* pTmp = NULL;
  403.                 m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer, (void**) &pTmp);
  404.                 if (pTmp)
  405.                 {
  406.                     // Set the size
  407.                     pTmp->SetSize(m_pFileBuffer->GetSize() + pBuffer->GetSize());
  408.                     // Copy in the old buffer
  409.                     memcpy(pTmp->GetBuffer(), m_pFileBuffer->GetBuffer(), m_pFileBuffer->GetSize()); /* Flawfinder: ignore */
  410.                     // Copy in the new buffer
  411.                     memcpy(pTmp->GetBuffer() + m_pFileBuffer->GetSize(), /* Flawfinder: ignore */
  412.                            pBuffer->GetBuffer(), pBuffer->GetSize());
  413.                     // Now get rid of the old buffer
  414.                     HX_RELEASE(m_pFileBuffer);
  415.                     m_pFileBuffer = pTmp;
  416.                     m_pFileBuffer->AddRef();
  417.                 }
  418.                 HX_RELEASE(pTmp);
  419.             }
  420.             else
  421.             {
  422.                 m_pFileBuffer = pBuffer;
  423.                 m_pFileBuffer->AddRef();
  424.             }
  425.             // Set the new state
  426.             m_ulState = kStateFileReadPending;
  427.             // Read the first kDefaultPacketSize bytes of the file
  428.             m_pFileObject->Read(kDefaultPacketSize);
  429.         }
  430.         else
  431.         {
  432.             // Set the state
  433.             m_ulState = kStateFileClosePending;
  434.             // Close the file
  435.             m_pFileObject->Close();
  436.         }
  437.     }
  438.     else
  439.     {
  440.         retVal = HXR_UNEXPECTED;
  441.     }
  442.     return retVal;
  443. }
  444. STDMETHODIMP CBrushFileFormat::WriteDone(HX_RESULT status)
  445. {
  446.     // We don't ever write, so we don't expect to get this...
  447.     return HXR_UNEXPECTED;
  448. }
  449. STDMETHODIMP CBrushFileFormat::CloseDone(HX_RESULT status)
  450. {
  451.     HX_RESULT retVal = HXR_OK;
  452.     if (m_ulState == kStateFileClosePending)
  453.     {
  454.         // We can't be initialized successfully if we
  455.         // don't have a file buffer
  456.         if (!m_pFileBuffer)
  457.         {
  458.             status = HXR_FAIL;
  459.         }
  460.         // Set the state
  461.         m_ulState = (SUCCEEDED(status) ? kStateFileFormatInitialized : kStateError);
  462.         // Send a stream done
  463.         m_pFormatResponse->InitDone(status);
  464.     }
  465.     else
  466.     {
  467.         retVal = HXR_UNEXPECTED;
  468.     }
  469.     return retVal;
  470. }
  471. HX_RESULT STDAPICALLTYPE CBrushFileFormat::HXCreateInstance(IUnknown** ppIUnknown)
  472. {
  473.     HX_RESULT retVal = HXR_FAIL;
  474.     if (ppIUnknown)
  475.     {
  476.         // Create the object
  477.         CBrushFileFormat* pObj = new CBrushFileFormat();
  478.         if (pObj)
  479.         {
  480.             // QI for IUnknown
  481.             retVal = pObj->QueryInterface(IID_IUnknown, (void**) ppIUnknown);
  482.         }
  483.     }
  484.     return retVal;
  485. }
  486. HX_RESULT STDAPICALLTYPE CBrushFileFormat::CanUnload2()
  487. {
  488.     return ((CHXBaseCountingObject::ObjectsActive() > 0) ? HXR_FAIL : HXR_OK );
  489. }
  490. void CBrushFileFormat::Deallocate()
  491. {
  492.     HX_RELEASE(m_pContext);
  493.     HX_RELEASE(m_pFileObject);
  494.     HX_RELEASE(m_pFormatResponse);
  495.     HX_RELEASE(m_pCommonClassFactory);
  496.     HX_RELEASE(m_pFileBuffer);
  497.     Reset();
  498. }
  499. void CBrushFileFormat::Reset()
  500. {
  501.     m_pContext            = NULL;
  502.     m_pFileObject         = NULL;
  503.     m_pFormatResponse     = NULL;
  504.     m_pCommonClassFactory = NULL;
  505.     m_pFileBuffer         = NULL;
  506.     m_ulState             = kStateConstructed;
  507.     m_bNullBrush          = FALSE;
  508. }
  509. BOOL CBrushFileFormat::IsNullBrush(IHXRequest* pRequest)
  510. {
  511.     BOOL bRet = FALSE;
  512.     if (pRequest)
  513.     {
  514.         // Get the request headers
  515.         IHXValues* pReqHdrs = NULL;
  516.         pRequest->GetRequestHeaders(pReqHdrs);
  517.         if (pReqHdrs)
  518.         {
  519.             // See if there was a "NullBrush" flag
  520.             IHXBuffer* pTmp = NULL;
  521.             pReqHdrs->GetPropertyCString("NullBrush", pTmp);
  522.             if (pTmp)
  523.             {
  524.                 // Yes, there WAS a "NullBrush" flag
  525.                 bRet = TRUE;
  526.             }
  527.             HX_RELEASE(pTmp);
  528.         }
  529.         HX_RELEASE(pReqHdrs);
  530.     }
  531.     return bRet;
  532. }