home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / ezrgb24.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-29  |  16.2 KB  |  658 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992 - 1996  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // EZrgb24
  13. //
  14. // A Transform filter for simple 24 bit RGB image FX
  15. //
  16.  
  17. #include <windows.h>
  18. #include <streams.h>
  19.  
  20. #include <initguid.h>
  21. #include <olectl.h>
  22. #include <olectlid.h>
  23.  
  24. #include "EZuids.h"
  25. #include "iEZ.h"
  26. #include "EZprop.h"
  27. #include "EZrgb24.h"
  28. #include "resource.h"
  29.  
  30. // setup
  31.  
  32. AMOVIESETUP_MEDIATYPE sudPinTypes = { &MEDIATYPE_Video        // clsMajorType
  33.                                       , &MEDIASUBTYPE_NULL }; // clsMinorType
  34.  
  35. AMOVIESETUP_PIN sudpPins [] =
  36. {
  37.     { L"Input"             // strName
  38.       , FALSE              // bRendered
  39.       , FALSE              // bOutput
  40.       , FALSE              // bZero
  41.       , FALSE              // bMany
  42.       , &CLSID_NULL        // clsConnectsToFilter
  43.       , NULL               // strConnectsToPin
  44.       , 1                  // nTypes
  45.       , &sudPinTypes       // lpTypes
  46.     },
  47.     { L"Output"            // strName
  48.       , FALSE              // bRendered
  49.       , TRUE               // bOutput
  50.       , FALSE              // bZero
  51.       , FALSE              // bMany
  52.       , &CLSID_NULL        // clsConnectsToFilter
  53.       , NULL               // strConnectsToPin
  54.       , 1                  // nTypes
  55.       , &sudPinTypes       // lpTypes
  56.     }
  57. };
  58.  
  59.  
  60. AMOVIESETUP_FILTER sudEZrgb24 = { &CLSID_EZrgb24            // clsID
  61.                                 , L"ImageFX: Easy RGB24"    // strName
  62.                                 , MERIT_DO_NOT_USE     // dwMerit
  63.                                 , 2                         // nPins
  64.                                 , sudpPins };               // lpPin
  65.  
  66.  
  67.  
  68. // COM Global table of objects in this dll
  69. CFactoryTemplate g_Templates[] = {
  70.  
  71.     {L"ImageFX: Easy RGB24", &CLSID_EZrgb24, CEZrgb24::CreateInstance},
  72.     {L"Easy RGB24 Property Page", &CLSID_EZrgb24PropertyPage, CEZrgb24Properties::CreateInstance}
  73. };
  74. // Count of objects listed in g_cTemplates
  75. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  76.  
  77.  
  78. // exported entry points for registration and unregistration (in this case they
  79. // only call through to default implmentations).
  80. //
  81.  
  82. HRESULT DllRegisterServer()
  83. {
  84.   return AMovieDllRegisterServer();
  85. }
  86.  
  87. HRESULT DllUnregisterServer()
  88. {
  89.   return AMovieDllUnregisterServer();
  90. }
  91.  
  92.  
  93. //
  94. // CEZrgb24::Constructor
  95. //
  96. CEZrgb24::CEZrgb24(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
  97.     : CTransformFilter(tszName, punk, CLSID_EZrgb24, phr)
  98.     , m_effect(IDC_RED)
  99.     , m_lBufferRequest(1)
  100.     , CPersistStream(punk, phr)
  101. {
  102.     char   sz[60];
  103.     GetProfileStringA("Quartz", "EffectStart", "2.0", sz, 60);
  104.     m_effectStartTime = COARefTime(atof(sz));
  105.     GetProfileStringA("Quartz", "EffectLength", "5.0", sz, 60);
  106.     m_effectTime = COARefTime(atof(sz));
  107. }
  108.  
  109.  
  110. //
  111. // CreateInstance
  112. //
  113. // Provide the way for COM to create a EZrgb24 object
  114. CUnknown *CEZrgb24::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
  115.  
  116.     CEZrgb24 *pNewObject = new CEZrgb24(NAME("ImageFX: Easy RGB24 Transform"), punk, phr);
  117.     if (pNewObject == NULL) {
  118.         *phr = E_OUTOFMEMORY;
  119.     }
  120.  
  121.     return pNewObject;
  122.  
  123. }
  124.  
  125. //
  126. // GetSetupData
  127. //
  128.  
  129. LPAMOVIESETUP_FILTER CEZrgb24::GetSetupData()
  130. {
  131.   return &sudEZrgb24;
  132. }
  133.  
  134.  
  135. //
  136. // NonDelegatingQueryInterface
  137. //
  138. // Reveals IIPEffect & ISpecifyPropertyPages
  139. STDMETHODIMP CEZrgb24::NonDelegatingQueryInterface(REFIID riid, void ** ppv) {
  140.  
  141.     if (riid == IID_IIPEffect) {
  142.         return GetInterface((IIPEffect *) this, ppv);
  143.     }
  144.     else if (riid == IID_ISpecifyPropertyPages) {
  145.         return GetInterface((ISpecifyPropertyPages *) this, ppv);
  146.     }
  147.     else {
  148.         return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
  149.     }
  150. }
  151.  
  152.  
  153. //
  154. // Transform
  155. //
  156. // Copy the input sample into thee output sample. Then transform
  157. // the output sample 'in place'.
  158. HRESULT CEZrgb24::Transform(IMediaSample *pIn, IMediaSample *pOut) {
  159.  
  160.  
  161. /**********************
  162. if we have all keyframes, then we shouldn't copy.
  163. if we have cinepak or indeo and are decompressing frame N, we need to have
  164. a decompressed frame N-1 available to calculate it, unless we are at a keyframe.
  165. So with keyframed codecs, you can't get away with applying the transform to
  166. change the frames in place, because you'll screw up the next frames decompression.
  167. *************************/
  168.  
  169.         
  170.     HRESULT hr = Copy(pIn, pOut);
  171.     if (FAILED(hr)) {
  172.         return hr;
  173.     }
  174.  
  175.     // check to see if it is time to do the sample.
  176.     CRefTime tStart, tStop ;
  177.     pIn->GetTime((REFERENCE_TIME *) &tStart, (REFERENCE_TIME *) &tStop);
  178.  
  179.     if ((tStart >= m_effectStartTime)
  180.          && (tStop <= (m_effectStartTime+m_effectTime)))
  181.     {
  182.         return Transform(pOut);
  183.     }
  184.     else // not the time to do the effect
  185.         return NOERROR;
  186. }
  187.  
  188.  
  189. //
  190. // Copy
  191. //
  192. // make Dest an identical copy of Source
  193. HRESULT CEZrgb24::Copy(IMediaSample *pSource, IMediaSample *pDest) const {
  194.  
  195.     {
  196.     // Copy the sample data
  197.  
  198.     BYTE *pSourceBuffer, *pDestBuffer;
  199.     long lSourceSize    = pSource->GetSize();
  200.     long lDestSize    = pDest->GetSize();
  201.  
  202.     ASSERT(lDestSize >= lSourceSize);
  203.  
  204.     pSource->GetPointer(&pSourceBuffer);
  205.     pDest->GetPointer(&pDestBuffer);
  206.  
  207.     CopyMemory( (PVOID) pDestBuffer
  208.               , (PVOID) pSourceBuffer
  209.               , lSourceSize
  210.               );
  211.     }
  212.     {
  213.     // copy the sample time
  214.  
  215.     REFERENCE_TIME TimeStart, TimeEnd;
  216.  
  217.     pSource->GetTime((REFERENCE_TIME *) &TimeStart,
  218.              (REFERENCE_TIME *) &TimeEnd);
  219.     pDest->SetTime(&TimeStart, &TimeEnd);
  220.     }
  221.     {
  222.     // Copy the Sync point property
  223.  
  224.     HRESULT hr = pSource->IsSyncPoint();
  225.     if (hr == S_OK) {
  226.         pDest->SetSyncPoint(TRUE);
  227.     }
  228.     else if (hr == S_FALSE) {
  229.         pDest->SetSyncPoint(FALSE);
  230.     }
  231.     else {    // an unexpected error has occured...
  232.         return E_UNEXPECTED;
  233.     }
  234.     }
  235.     {
  236.     // Copy the media type
  237.  
  238.     AM_MEDIA_TYPE *pMediaType;
  239.     pSource->GetMediaType(&pMediaType);
  240.     pDest->SetMediaType(pMediaType);
  241.         DeleteMediaType(pMediaType);
  242.     }
  243.     {
  244.     // Copy the preroll property
  245.  
  246.     HRESULT hr = pSource->IsPreroll();
  247.     if (hr == S_OK) {
  248.         pDest->SetPreroll(TRUE);
  249.     }
  250.     else if (hr == S_FALSE) {
  251.         pDest->SetPreroll(FALSE);
  252.     }
  253.     else {    // an unexpected error has occured...
  254.         return E_UNEXPECTED;
  255.     }
  256.     }
  257.     {
  258.     // Copy the discontinuity property
  259.  
  260.     HRESULT hr = pSource->IsDiscontinuity();
  261.     if (hr == S_OK) {
  262.         pDest->SetDiscontinuity(TRUE);
  263.     }
  264.     else if (hr == S_FALSE) {
  265.         pDest->SetDiscontinuity(FALSE);
  266.     }
  267.     else {    // an unexpected error has occured...
  268.         return E_UNEXPECTED;
  269.     }
  270.     }
  271.     {
  272.     // Copy the actual data length
  273.  
  274.     long lDataLength = pSource->GetActualDataLength();
  275.     pDest->SetActualDataLength(lDataLength);
  276.     }
  277.  
  278.     return NOERROR;
  279. }
  280.  
  281.  
  282. //
  283. // Transform
  284. //
  285. // 'In place' apply Image FX to this sample
  286. HRESULT CEZrgb24::Transform(IMediaSample *pMediaSample) {
  287.  
  288.     AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
  289.  
  290.     VIDEOINFO *pvi = (VIDEOINFO *) pType->pbFormat;
  291.  
  292.  
  293.     BYTE    *pData;
  294.     long    lDataLen;
  295.     unsigned int        grey,grey2;
  296.  
  297.     pMediaSample->GetPointer(&pData);
  298.     lDataLen = pMediaSample->GetSize();
  299.  
  300.     int iPixel;
  301.     int iPixelSize = pvi->bmiHeader.biBitCount / 8;
  302.     int cxImage = pvi->bmiHeader.biWidth;
  303.     int cyImage = pvi->bmiHeader.biHeight;
  304.     int cbImage = cyImage * cxImage * iPixelSize;
  305.     int numPixels = pvi->bmiHeader.biWidth * pvi->bmiHeader.biHeight;
  306.     int x,y;
  307.     int temp;
  308.     RGBTRIPLE* prgb;
  309.  
  310. //    CAutoLock lShared(&m_cSharedState);
  311.  
  312.     switch (m_effect)
  313.     {
  314.         case IDC_NONE:
  315.             break ;
  316.         case IDC_RED:   // Zero out the green & blue components to leave only the red.
  317.                         // For better visual results, compute a greyscale value for the pixel
  318.                         // and stuff that into the red component.      
  319.             prgb = (RGBTRIPLE*) pData;
  320.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  321.             {
  322.                 prgb->rgbtGreen = 0;
  323.                 prgb->rgbtBlue = 0;
  324.             }
  325.             break;
  326.     
  327.         case IDC_GREEN:
  328.             prgb = (RGBTRIPLE*) pData;
  329.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  330.             {
  331.                 prgb->rgbtRed = 0;
  332.                 prgb->rgbtBlue = 0;
  333.             }
  334.             break;
  335.  
  336.         case IDC_BLUE:
  337.             prgb = (RGBTRIPLE*) pData;
  338.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  339.             {
  340.                 prgb->rgbtRed = 0;
  341.                 prgb->rgbtGreen = 0;
  342.             }
  343.             break;
  344.  
  345.         case IDC_DARKEN:  // bitwise shift each component to the right by 2.
  346.                           // this results in the image getting much darker.
  347.             prgb = (RGBTRIPLE*) pData;
  348.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  349.             {
  350.                 prgb->rgbtRed = prgb->rgbtRed >> 2;
  351.                 prgb->rgbtGreen = prgb->rgbtGreen >> 2;
  352.                 prgb->rgbtBlue = prgb->rgbtBlue >> 2;
  353.             }
  354.             break;
  355.  
  356.  
  357.         case IDC_XOR:     // Toggle each bit.  This gives a sort of X-ray effect.
  358.             prgb = (RGBTRIPLE*) pData;
  359.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  360.             {
  361.                 prgb->rgbtRed = prgb->rgbtRed ^ 0xff;
  362.                 prgb->rgbtGreen = prgb->rgbtGreen ^ 0xff;
  363.                 prgb->rgbtBlue = prgb->rgbtBlue ^ 0xff;
  364.             }
  365.             break;
  366.     
  367.         case IDC_POSTERIZE:  // zero out the 5 LSB per each component
  368.             prgb = (RGBTRIPLE*) pData;
  369.             for (iPixel=0; iPixel <    numPixels; iPixel++, prgb++)
  370.             {
  371.                 prgb->rgbtRed = prgb->rgbtRed & 0xe0;
  372.                 prgb->rgbtGreen = prgb->rgbtGreen & 0xe0;
  373.                 prgb->rgbtBlue = prgb->rgbtBlue & 0xe0;
  374.             }
  375.             break;
  376.  
  377.         case IDC_BLUR:  // take pixel and its neighbor two pixles to the right.
  378.                         // average them.
  379.                         // this blurs them and produces a subtle motion effect.
  380.             prgb = (RGBTRIPLE*) pData;
  381.             for (y = 0 ; y < pvi->bmiHeader.biHeight; y++)
  382.             {
  383.                 for (x = 2 ; x < pvi->bmiHeader.biWidth; x++,prgb++)
  384.                 {
  385.                     prgb->rgbtRed = (prgb->rgbtRed + prgb[2].rgbtRed) >> 1;
  386.                     prgb->rgbtGreen = (prgb->rgbtGreen + prgb[2].rgbtGreen) >> 1;
  387.                     prgb->rgbtBlue = (prgb->rgbtBlue + prgb[2].rgbtBlue) >> 1;
  388.                 }
  389.                 prgb +=2;
  390.             }
  391.             break;
  392.     
  393.         case IDC_GREY:     // An excellent greyscale calculation is:
  394.                         //         grey = (30 * red + 59 * green + 11 * blue) / 100.
  395.                         // This is a bit too slow.  A faster calculation is:
  396.                         //        grey = (red + green) / 2.
  397.             prgb = (RGBTRIPLE*) pData;
  398.             for (iPixel=0; iPixel < numPixels ; iPixel++, prgb++)
  399.             {
  400.                 grey = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
  401.                 prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) grey;
  402.             }
  403.             break;
  404.  
  405.         case IDC_EMBOSS:// Really sleazy emboss.
  406.                         // Rather than using a nice 3x3 convulution matrix,
  407.                         // we compare the greyscale values of two neighbors.
  408.                         // If they are not different, then a mid grey (128, 128, 128)
  409.                         // is supplied.  Large differences get father away from the mid grey.
  410.             prgb = (RGBTRIPLE*) pData;
  411.             for (y = 0 ; y < pvi->bmiHeader.biHeight; y++)
  412.             {
  413.                 grey2 = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
  414.                 prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) 128;
  415.                 prgb++;
  416.                 for (x = 1 ; x < pvi->bmiHeader.biWidth; x++)
  417.                 {
  418.                     grey = (prgb->rgbtRed + prgb->rgbtGreen) >> 1;
  419.                     temp = grey - grey2;
  420.                     if (temp > 127) temp = 127;
  421.                     if (temp < -127) temp = -127;
  422.                     temp += 128;
  423.                     prgb->rgbtRed = prgb->rgbtGreen = prgb->rgbtBlue = (BYTE) temp;
  424.                     grey2 = grey;
  425.                     prgb++;
  426.                 }
  427.             }    
  428.             break;
  429.     }
  430.     return NOERROR;
  431. }
  432.  
  433.  
  434. //
  435. // CheckInputType
  436. //
  437. // check the input type is OK.
  438. // return an error otherwise
  439. HRESULT CEZrgb24::CheckInputType(const CMediaType *mtIn) {
  440.  
  441.     // check this is a VIDEOINFO type
  442.     if (*mtIn->FormatType() != FORMAT_VideoInfo) {
  443.         return E_INVALIDARG;
  444.     }
  445.  
  446.     if (CanPerformEZrgb24(mtIn)) {
  447.         return NOERROR;
  448.     }
  449.     else {
  450.         return E_FAIL;
  451.     }
  452. }
  453.  
  454.  
  455. //
  456. // CheckTransform
  457. //
  458. // If these types are OK as input and output (I can transform them
  459. // and they are the same) return NOERROR. Otherwise return an
  460. // error code
  461. HRESULT CEZrgb24::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) {
  462.  
  463.     if (   CanPerformEZrgb24(mtIn)
  464.         && (*mtIn == *mtOut)
  465.        ) {
  466.  
  467.         return NOERROR;
  468.     }
  469.     else {
  470.  
  471.         return E_FAIL;
  472.     }
  473. }
  474.  
  475.  
  476. //
  477. // DecideBufferSize
  478. //
  479. // Tell the output pin's allocator what size buffers we
  480. // require. Can only do this when the input is connected
  481. HRESULT CEZrgb24::DecideBufferSize(IMemAllocator *pAlloc,
  482.                    ALLOCATOR_PROPERTIES *pProperties) {
  483.  
  484.     if (!m_pInput->IsConnected()) {
  485.         return E_UNEXPECTED;
  486.     }
  487.     else {
  488.  
  489.     ALLOCATOR_PROPERTIES Request, Actual;
  490.     Request.cBuffers    = 1;
  491.     Request.cbBuffer    = m_pInput->CurrentMediaType().GetSampleSize();
  492.     Request.cbAlign        = 1;
  493.     Request.cbPrefix    = 0;
  494.  
  495.         HRESULT hr = pAlloc->SetProperties( &Request, &Actual );
  496.     if (FAILED(hr)) {
  497.        return hr;
  498.     }
  499.  
  500.     if ( (Request.cBuffers > Actual.cBuffers)
  501.         || (Request.cbBuffer > Actual.cbBuffer)
  502.         || (Request.cbAlign != Actual.cbAlign)
  503.        ) {
  504.     
  505.         return E_FAIL;
  506.     }
  507.     }
  508.  
  509.     return NOERROR;
  510. }
  511.  
  512.  
  513. //
  514. // GetMediaType
  515. //
  516. // I support 1 type, namely the type of the input pin. This
  517. // is only available if my input is connected.
  518. HRESULT CEZrgb24::GetMediaType(int iPosition, CMediaType *pMediaType) {
  519.  
  520.     if (m_pInput->IsConnected()) {
  521.         if (iPosition<0) {
  522.             return E_INVALIDARG;
  523.         }
  524.         if (iPosition>0) {
  525.             return VFW_S_NO_MORE_ITEMS;
  526.         }
  527.  
  528.     *pMediaType = m_pInput->CurrentMediaType();
  529.  
  530.     return NOERROR;
  531.     }
  532.     else {
  533.         return E_UNEXPECTED;
  534.     }
  535. }
  536.  
  537. #define WRITEOUT(var)  hr = pStream->Write(&var, sizeof(var), NULL); \
  538.                if (FAILED(hr)) return hr;
  539.  
  540. #define READIN(var)    hr = pStream->Read(&var, sizeof(var), NULL); \
  541.                if (FAILED(hr)) return hr;
  542.  
  543. STDMETHODIMP CEZrgb24::GetClassID(CLSID *pClsid)
  544. {
  545.     *pClsid = CLSID_EZrgb24;
  546.     return NOERROR;
  547. }
  548.  
  549. HRESULT CEZrgb24::ScribbleToStream(IStream *pStream)
  550. {
  551.     HRESULT hr;
  552.     WRITEOUT(m_effect);
  553.     WRITEOUT(m_effectStartTime);
  554.     WRITEOUT(m_effectTime);
  555.     return NOERROR;
  556. }
  557.  
  558.  
  559. HRESULT CEZrgb24::ReadFromStream(IStream *pStream)
  560. {
  561.     HRESULT hr;
  562.     READIN(m_effect);
  563.     READIN(m_effectStartTime);
  564.     READIN(m_effectTime);
  565.     return NOERROR;
  566. }
  567.  
  568.  
  569. //
  570. // --- ISpecifyPropertyPages ---
  571. //
  572.  
  573.  
  574. //
  575. // GetPages
  576. //
  577. // Returns the clsid's of the property pages we support
  578. STDMETHODIMP CEZrgb24::GetPages(CAUUID *pPages) {
  579.  
  580.     pPages->cElems = 1;
  581.     pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  582.     if (pPages->pElems == NULL) {
  583.         return E_OUTOFMEMORY;
  584.     }
  585.     *(pPages->pElems) = CLSID_EZrgb24PropertyPage;
  586.  
  587.     return NOERROR;
  588. }
  589.  
  590.  
  591. //
  592. // CanPerformEZrgb24
  593. //
  594. // Check if this is a paletised format
  595. BOOL CEZrgb24::CanPerformEZrgb24(const CMediaType *pMediaType) const {
  596.  
  597.     VIDEOINFO *pvi;
  598.  
  599.  
  600.  
  601.     if (   (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video))
  602.         && (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24))  )
  603.        {
  604.         pvi = (VIDEOINFO *) pMediaType->Format();
  605.         return (pvi->bmiHeader.biBitCount == 24);  // media type & videoinfo agree
  606.     }
  607.  
  608.     else {    // can't process this
  609.         return FALSE;
  610.     }
  611. }
  612.  
  613.  
  614. //
  615. // --- IIPEffect ---
  616. //
  617.  
  618.  
  619. //
  620. // get_IPEffect
  621. //
  622. STDMETHODIMP CEZrgb24::get_IPEffect(int *IPEffect, REFTIME *start, REFTIME *length)
  623. {
  624.  
  625.     CAutoLock l(&m_EZrgb24Lock);
  626.  
  627.     *IPEffect = m_effect;
  628.     *start = COARefTime(m_effectStartTime);
  629.     *length = COARefTime(m_effectTime);
  630.  
  631.     DbgLog((LOG_TRACE, 1, TEXT("get_IPEffect: %d"), *IPEffect));
  632.  
  633.     return NOERROR;
  634. }
  635.  
  636.  
  637. //
  638. // put_IPEffect
  639. //
  640. STDMETHODIMP CEZrgb24::put_IPEffect(int IPEffect, REFTIME start, REFTIME length)
  641. {
  642.  
  643.     CAutoLock l(&m_EZrgb24Lock);
  644.  
  645.     m_effect = IPEffect;
  646.     m_effectStartTime = COARefTime(start);
  647.     m_effectTime = COARefTime(length);
  648.  
  649.     SetDirty(TRUE);
  650.  
  651.     DbgLog((LOG_TRACE, 1, TEXT("put_IPEffect: %d"), m_effect));
  652.  
  653.     return NOERROR;
  654. }
  655.  
  656.  
  657.  
  658.