home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / iamovie.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-29  |  21.2 KB  |  665 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. #include <streams.h>
  13. #include "Ext_Enum.h"
  14.  
  15. class CAMovie : public IAMovie, public CUnknown
  16. {
  17. private:
  18.     IGraphBuilder   *   pGB;
  19.     IMediaControl   *   pMC;
  20.     IMediaEvent     *   pME;
  21.     IMediaPosition  *   pMP;
  22.  
  23. protected:
  24.     ~CAMovie();
  25.     CAMovie(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
  26.  
  27.     // Disconnect all pins.  If a filter has no pins, remove it completely
  28.     // This is to part-destroy a filter graph, leaving only those filters
  29.     // that may be usefult for rendering a file or pin after this function
  30.     // has been called.
  31.     HRESULT DisconnectAllAndRemoveIsolates();
  32.  
  33.     // For all filters in graph, if the filter has pins, and all are unconnected,
  34.     // then remove the filter from the graph.
  35.     HRESULT RemoveAllUnconnected();
  36.  
  37. public:
  38.     DECLARE_IUNKNOWN
  39.  
  40.     static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
  41.  
  42.     STDMETHODIMP NonDelegatingQueryInterface(REFIID iid, void ** ppv);
  43.  
  44.     // IFilterGraph
  45.  
  46.     // Add a filter to the graph and name it with *pName.
  47.     // If the name is not unique, The request will fail.
  48.     // The Filter graph will call the JoinFilterGraph
  49.     // member function of the filter to inform it.
  50.     // This must be called before attempting Connect, ConnectDirect or Render
  51.     // for pins of the filter.
  52.  
  53.     STDMETHODIMP AddFilter
  54.         ( IFilter * pFilter,
  55.           LPCWSTR pName
  56.         );
  57.  
  58.     // Remove a filter from the graph. The filter graph implementation
  59.     // will inform the filter that it is being removed.
  60.  
  61.     STDMETHODIMP RemoveFilter
  62.         ( IFilter * pFilter
  63.         );
  64.  
  65.     // Set *ppEnum to be an enumerator for all filters in the graph.
  66.  
  67.     STDMETHODIMP EnumFilters
  68.         ( IEnumFilters **ppEnum
  69.         );
  70.  
  71.     // Set *ppFilter to be the filter which was added with the name *pName
  72.     // Will fail and set *ppFilter to NULL if the name is not in this graph.
  73.  
  74.     STDMETHODIMP FindFilterByName
  75.         ( LPCWSTR pName,
  76.           IFilter ** ppFilter
  77.         );
  78.  
  79.     //==========================================================================
  80.     // Low level connection functions
  81.     //==========================================================================
  82.  
  83.     // Connect these two pins directly (i.e. without intervening filters)
  84.     // the media type is optional, and may be partially specified (that is
  85.     // the subtype and/or format type may be GUID_NULL). See IPin::Connect
  86.     // for details of the media type parameter.
  87.     STDMETHODIMP ConnectDirect
  88.         ( IPin * ppinOut,              // the output pin
  89.           IPin * ppinIn,               // the input pin
  90.           const AM_MEDIA_TYPE* pmt     // optional mediatype
  91.         );
  92.  
  93.     // On a separate thread (which will not hold any relevant locks)
  94.     // Break the connection that this pin has and reconnect it to the
  95.     // same other pin.
  96.  
  97.     STDMETHODIMP Reconnect
  98.         ( IPin * ppin        // the pin to disconnect and reconnect
  99.         );
  100.  
  101.     // Disconnect this pin, if connected.  Successful no-op if not connected.
  102.  
  103.     STDMETHODIMP Disconnect
  104.         ( IPin * ppin
  105.         );
  106.  
  107.     //==========================================================================
  108.     // intelligent connectivity - now in IGraphBuilder, axextend.idl
  109.     //==========================================================================
  110.  
  111.     //==========================================================================
  112.     // Whole graph functions
  113.     //==========================================================================
  114.  
  115.     // Once a graph is built, it can behave as a (composite) filter.
  116.     // To control this filter, QueryInterface for IMediaFilter.
  117.  
  118.     // The filtergraph will by default ensure that the graph has a sync source
  119.     // when it is made to Run.  SetSyncSource(NULL) will prevent that and allow
  120.     // all the filters to run unsynchronised until further notice.
  121.     // SetDefaultSyncSource will set the default sync source (the same as would
  122.     // have been set by default on the first call to Run).
  123.     STDMETHODIMP SetDefaultSyncSource(void);
  124.  
  125.  
  126.  
  127.     // IGraphBuilder
  128.  
  129.     // Connect these two pins directly or indirectly, using transform filters
  130.     // if necessary.
  131.  
  132.     STDMETHODIMP Connect
  133.     ( IPin * ppinOut,    // the output pin
  134.       IPin * ppinIn      // the input pin
  135.     );
  136.  
  137.     // Connect this output pin directly or indirectly, using transform filters
  138.     // if necessary to something that will render it.
  139.  
  140.     STDMETHODIMP Render
  141.     ( IPin * ppinOut     // the output pin
  142.     );
  143.  
  144.     // This pair of methods are a cross between the IGraphBuilder ones and the IMediaControl ones,
  145.     // unfortunate perhaps, but they do make the nicest C / C++ interfaces .
  146.  
  147.     // adds and connects filters needed to play the specified file
  148.     STDMETHODIMP RenderFile( LPCWSTR strFilename );
  149.  
  150.     // adds to the graph the source filter that can read this file,
  151.     // and returns an IFilterInfo object for it
  152.     STDMETHODIMP AddSourceFilter( LPCWSTR strFilename, IFilter ** ppUnk);
  153.  
  154.  
  155.     // IMediaControl methods
  156.     STDMETHODIMP Run();
  157.     STDMETHODIMP Pause();
  158.     STDMETHODIMP Stop();
  159.  
  160.     //returns the state. same semantics as IMediaFilter::GetState
  161.     STDMETHODIMP GetState(
  162.                 LONG msTimeout,
  163.                 FILTER_STATE* pfs);
  164.  
  165.     // IMediaEvent
  166.  
  167.     // get back the event handle. This is manual-reset
  168.     // (don't - it's reset by the event mechanism) and remains set
  169.     // when events are queued, and reset when the queue is empty.
  170.     STDMETHODIMP GetEventHandle(
  171.                     HEVENT * hEvent);
  172.  
  173.     // remove the next event notification from the head of the queue and
  174.     // return it. Waits up to msTimeout millisecs if there are no events.
  175.     // if a timeout occurs without any events, this method will return
  176.     // E_ABORT, and the value of the event code and other parameters
  177.     // is undefined.
  178.     STDMETHODIMP GetEvent(
  179.                     long * lEventCode,
  180.                     long * lParam1,
  181.                     long * lParam2,
  182.                     long msTimeout
  183.                     );
  184.  
  185.     // Calls GetEvent repeatedly discarding events until it finds a
  186.     // completion event (EC_COMPLETE, EC_ERRORABORT, or EC_USERABORT).
  187.     // The completion event is removed from the queue and returned
  188.     // in pEvCode. Note that the object is still in running mode until
  189.     // a Pause or Stop call is made.
  190.     // If the timeout occurs, *pEvCode will be 0 and E_ABORT will be
  191.     // returned.
  192.     STDMETHODIMP WaitForCompletion(
  193.                     long msTimeout,
  194.                     long * pEvCode);
  195.  
  196.     // cancels any system handling of the specified event code
  197.     // and ensures that the events are passed straight to the application
  198.     // (via GetEvent) and not handled. A good example of this is
  199.     // EC_REPAINT: default handling for this ensures the painting of the
  200.     // window and does not get posted to the app.
  201.     STDMETHODIMP CancelDefaultHandling(
  202.                     long lEvCode);
  203.  
  204.     // restore the normal system default handling that may have been
  205.     // cancelled by CancelDefaultHandling().
  206.     STDMETHODIMP RestoreDefaultHandling( long lEvCode);
  207.  
  208.  
  209.     // IMediaPosition
  210.     // properties
  211.     STDMETHODIMP get_Duration(
  212.                 REFTIME* plength);
  213.  
  214.     STDMETHODIMP put_CurrentPosition(
  215.                 REFTIME llTime);
  216.  
  217.     STDMETHODIMP get_CurrentPosition(
  218.                 REFTIME* pllTime);
  219.  
  220.     STDMETHODIMP get_StopTime(
  221.                 REFTIME* pllTime);
  222.  
  223.     STDMETHODIMP put_StopTime(
  224.                 REFTIME llTime);
  225.  
  226.     STDMETHODIMP get_PrerollTime(
  227.                 REFTIME* pllTime);
  228.     STDMETHODIMP put_PrerollTime(
  229.                 REFTIME llTime);
  230.  
  231.     STDMETHODIMP put_Rate(
  232.                 double dRate);
  233.     STDMETHODIMP get_Rate(
  234.                 double * pdRate);
  235.  
  236.     /* New methods */
  237.  
  238.     // Remove all filters
  239.     STDMETHODIMP  RemoveAllFilters();
  240.  
  241.     // If the filter graph can be Run to completion, run it and wait for it to complete
  242.     STDMETHODIMP  Play();
  243.     // As above, but RenderNewFile first
  244.     STDMETHODIMP  PlayFile( LPCWSTR strFilename );
  245.  
  246.     // Render all unconnected output pins
  247.     STDMETHODIMP  RenderAll();
  248.     // Render supplied files "as if" the filter graoh were first emptied
  249.     STDMETHODIMP  RenderNewFile( LPCWSTR strFilename );
  250.  
  251.     STDMETHODIMP  EnumFiltersByInterface( REFIID iid, IEnumFilters ** pEnumFilters );
  252.     // Enum pins over the entire graph
  253.     STDMETHODIMP  EnumPins( IEnumPins ** ppEnum );
  254.     STDMETHODIMP  EnumPinsIn( IEnumPins ** ppEnum );
  255.     STDMETHODIMP  EnumPinsOut( IEnumPins ** ppEnum );
  256. };
  257.  
  258.  
  259.  
  260. CFactoryTemplate g_Templates[]=
  261. {   {L"ActiveMovie Sample PID", &CLSID_AMovie,   CAMovie::CreateInstance},
  262. };
  263. int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
  264.  
  265.  
  266. CAMovie::~CAMovie()
  267. { /* nothing to do */ }
  268.  
  269. CAMovie::CAMovie(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr)
  270. : CUnknown( pName, pUnk, phr )
  271. , pGB(0), pMC(0), pME(0), pMP(0)
  272. {
  273.     if (!pUnk) *phr = VFW_E_NEED_OWNER;
  274.     else if SUCCEEDED(*phr)
  275.     {
  276.         *phr = pUnk->QueryInterface( IID_IGraphBuilder, reinterpret_cast<void**>(&pGB) );
  277.         if SUCCEEDED(*phr)
  278.         {
  279.             pGB->Release();
  280.             *phr = pUnk->QueryInterface( IID_IMediaControl, reinterpret_cast<void**>(&pMC) );
  281.             if SUCCEEDED(*phr)
  282.             {
  283.                 pMC->Release();
  284.                 *phr = pUnk->QueryInterface( IID_IMediaEvent, reinterpret_cast<void**>(&pME) );
  285.                 if SUCCEEDED(*phr)
  286.                 {
  287.                     pME->Release();
  288.                     *phr = pUnk->QueryInterface( IID_IMediaPosition, reinterpret_cast<void**>(&pMP) );
  289.                     if SUCCEEDED(*phr) pMP->Release();
  290.                 }
  291.             }
  292.         }
  293.     }
  294. }
  295.  
  296. CUnknown * CAMovie::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
  297. {
  298.     CUnknown * result = 0;
  299.     result = new CAMovie( NAME("IAMovie Class"), pUnk, phr );
  300.     if ( !result ) *phr = E_OUTOFMEMORY;
  301.     return result;
  302. }
  303.  
  304. STDMETHODIMP CAMovie::NonDelegatingQueryInterface(REFIID iid, void ** ppv)
  305. {
  306.     if ( iid == IID_IAMovie )
  307.     {
  308.         return GetInterface(static_cast<IAMovie *>(this), ppv );
  309.     }
  310.     else
  311.     {
  312.     return CUnknown::NonDelegatingQueryInterface(iid, ppv);
  313.     }
  314. }
  315.  
  316.  
  317. // IFilterGraph (pGB)
  318. STDMETHODIMP CAMovie::AddFilter( IFilter * pFilter, LPCWSTR pName )
  319. { return pGB->AddFilter( pFilter, pName ); }
  320. STDMETHODIMP CAMovie::RemoveFilter( IFilter * pFilter )
  321. { return pGB->RemoveFilter( pFilter ); }
  322. STDMETHODIMP CAMovie::EnumFilters( IEnumFilters **ppEnum )
  323. { return pGB->EnumFilters( ppEnum ); }
  324. STDMETHODIMP CAMovie::FindFilterByName( LPCWSTR pName, IFilter ** ppFilter )
  325. { return pGB->FindFilterByName( pName, ppFilter ); }
  326. STDMETHODIMP CAMovie::ConnectDirect( IPin * ppinOut, IPin * ppinIn, const AM_MEDIA_TYPE* pmt )
  327. { return pGB->ConnectDirect( ppinOut, ppinIn, pmt ); }
  328. STDMETHODIMP CAMovie::Reconnect( IPin * ppin )
  329. { return pGB->Reconnect( ppin ); }
  330. STDMETHODIMP CAMovie::Disconnect( IPin * ppin )
  331. { return pGB->Disconnect( ppin ); }
  332. STDMETHODIMP CAMovie::SetDefaultSyncSource( )
  333. { return pGB->SetDefaultSyncSource( ); }
  334.  
  335.  
  336. // IGraphBuilder (pGB)
  337. STDMETHODIMP CAMovie::Connect( IPin * ppinOut, IPin * ppinIn )
  338. { return pGB->Connect( ppinOut, ppinIn ); }
  339. STDMETHODIMP CAMovie::Render( IPin * ppinOut )
  340. { return pGB->Render( ppinOut ); }
  341.  
  342.  
  343. // This pair of methods are a cross between the IGraphBuilder ones and the IMediaControl ones,
  344. // unfortunate perhaps, but they do make the nicest C / C++ interfaces .
  345. STDMETHODIMP CAMovie::AddSourceFilter( LPCWSTR strFilename, IFilter ** ppUnk )
  346. {
  347.     const LPWSTR fn = const_cast<LPWSTR>(strFilename);
  348.     return pGB->AddSourceFilter( fn, fn, ppUnk );
  349. }
  350.  
  351. STDMETHODIMP CAMovie::RenderFile( LPCWSTR strFilename )
  352. {
  353.     const LPWSTR fn = const_cast<LPWSTR>(strFilename);
  354.     return pGB->RenderFile( fn, fn );
  355. }
  356.  
  357.  
  358. // IMediaControl (pMC)
  359. STDMETHODIMP CAMovie::Run( )
  360. { return pMC->Run( ); }
  361. STDMETHODIMP CAMovie::Pause( )
  362. { return pMC->Pause( ); }
  363. STDMETHODIMP CAMovie::Stop( )
  364. { return pMC->Stop( ); }
  365. STDMETHODIMP CAMovie::GetState( LONG msTimeout, FILTER_STATE* pfs )
  366. { return pMC->GetState( msTimeout, (long *)pfs ); }
  367.  
  368.  
  369.  
  370. // IMediaEvent (pME)
  371. STDMETHODIMP CAMovie::GetEventHandle( HEVENT * hEvent )
  372. { return pME->GetEventHandle( (long *)hEvent ); }
  373. STDMETHODIMP CAMovie::GetEvent( long * lEventCode, long * lParam1, long * lParam2, long msTimeout )
  374. { return pME->GetEvent( lEventCode, lParam1, lParam2, msTimeout ); }
  375. STDMETHODIMP CAMovie::WaitForCompletion( long msTimeout, long * pEvCode )
  376. { return pME->WaitForCompletion( msTimeout, pEvCode ); }
  377. STDMETHODIMP CAMovie::CancelDefaultHandling( long lEvCode )
  378. { return pME->CancelDefaultHandling( lEvCode ); }
  379. STDMETHODIMP CAMovie::RestoreDefaultHandling( long lEvCode )
  380. { return pME->RestoreDefaultHandling( lEvCode ); }
  381.  
  382.  
  383. // IMediaPosition (pMP )
  384. STDMETHODIMP CAMovie::get_Duration( REFTIME* plength )
  385. { return pMP->get_Duration( plength ); }
  386. STDMETHODIMP CAMovie::put_CurrentPosition( REFTIME llTime )
  387. { return pMP->put_CurrentPosition( llTime ); }
  388. STDMETHODIMP CAMovie::get_CurrentPosition( REFTIME* pllTime )
  389. { return pMP->get_CurrentPosition( pllTime ); }
  390. STDMETHODIMP CAMovie::get_StopTime( REFTIME* pllTime )
  391. { return pMP->get_StopTime( pllTime ); }
  392. STDMETHODIMP CAMovie::put_StopTime( REFTIME llTime )
  393. { return pMP->put_StopTime( llTime ); }
  394. STDMETHODIMP CAMovie::get_PrerollTime( REFTIME* pllTime )
  395. { return pMP->get_PrerollTime( pllTime ); }
  396. STDMETHODIMP CAMovie::put_PrerollTime( REFTIME llTime )
  397. { return pMP->put_PrerollTime( llTime ); }
  398. STDMETHODIMP CAMovie::put_Rate( double dRate )
  399. { return pMP->put_Rate( dRate ); }
  400. STDMETHODIMP CAMovie::get_Rate( double * pdRate )
  401. { return pMP->get_Rate( pdRate ); }
  402.  
  403.  
  404.  
  405. // New methods
  406.  
  407. // Remove all filters
  408. STDMETHODIMP CAMovie::RemoveAllFilters()
  409. {
  410.     HRESULT  hr;
  411.  
  412.     IEnumFilters * piEnumFilters;
  413.     hr = EnumFilters( &piEnumFilters );
  414.     if SUCCEEDED(hr)
  415.     {
  416.         CGenericList<IFilter> FilterList("List of filters to be removed");
  417.  
  418.         IFilter * piFilter;
  419.         while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
  420.         {
  421.             FilterList.AddTail( piFilter );
  422.         }
  423.         piEnumFilters->Release();
  424.         while ( piFilter = FilterList.RemoveHead() )
  425.         {
  426.             hr = RemoveFilter( piFilter );
  427.             piFilter->Release();
  428.         }
  429.     }
  430.     return hr;
  431. }
  432.  
  433. // If the filter graph can be Run to completion, run it and wait for it to complete
  434. STDMETHODIMP  CAMovie::Play()
  435. {
  436.     HRESULT hr;
  437.     REFTIME duration;
  438.     hr = get_Duration( &duration );
  439.     if ( SUCCEEDED( hr ) && duration > 0 )
  440.     {
  441.         hr = Run();
  442.         if SUCCEEDED(hr)
  443.         {
  444.             long evCode;
  445.             WaitForCompletion( INFINITE, &evCode );
  446.         }
  447.         Stop();
  448.     }
  449.     return hr;
  450. }
  451.  
  452. STDMETHODIMP  CAMovie::PlayFile( LPCWSTR strFilename )
  453. {
  454.     HRESULT hr;
  455.     hr = RenderNewFile( strFilename );
  456.     if SUCCEEDED(hr)
  457.     {
  458.         hr = Play();
  459.     }
  460.     return hr;
  461. }
  462.  
  463. STDMETHODIMP CAMovie::RenderAll( )
  464. {
  465.     HRESULT hr = NOERROR;
  466.     CImpIEnumPinsOutOverGraph EnumOutPins( this, &hr );
  467.     if SUCCEEDED(hr)
  468.     {
  469.         IPin * piPin;
  470.  
  471.         while ( EnumOutPins.Next( 1, &piPin, 0 ) == NOERROR )
  472.         {
  473.             Render( piPin );
  474.         }
  475.     }
  476.     return hr;
  477. }
  478.  
  479. STDMETHODIMP CAMovie::RenderNewFile( LPCWSTR strFilename )
  480. {
  481.     HRESULT hr;
  482.     DisconnectAllAndRemoveIsolates();
  483.     hr = RenderFile( strFilename );
  484.     RemoveAllUnconnected();
  485.     return hr;
  486. }
  487.  
  488. STDMETHODIMP CAMovie::EnumFiltersByInterface( REFIID iid, IEnumFilters ** ppEnum )
  489. {
  490.     HRESULT hr = NOERROR;
  491.     *ppEnum = new CImpIEnumFilters( pGB, iid );
  492.     if (!*ppEnum) hr = E_OUTOFMEMORY;
  493.     else if FAILED(hr)
  494.     {
  495.         delete *ppEnum;
  496.         *ppEnum = 0;
  497.     }
  498.     return hr;
  499. }
  500.  
  501. STDMETHODIMP CAMovie::EnumPins( IEnumPins ** ppEnum )
  502. {
  503.     HRESULT hr = NOERROR;
  504.     *ppEnum = new CImpIEnumPinsOverGraph( pGB, &hr );
  505.     if (!*ppEnum) hr = E_OUTOFMEMORY;
  506.     else if FAILED(hr)
  507.     {
  508.         delete *ppEnum;
  509.         *ppEnum = 0;
  510.     }
  511.     return hr;
  512. }
  513.  
  514. STDMETHODIMP CAMovie::EnumPinsIn( IEnumPins ** ppEnum )
  515. {
  516.     HRESULT hr = NOERROR;
  517.     *ppEnum = new CImpIEnumPinsInOverGraph( pGB, &hr );
  518.     if (!*ppEnum) hr = E_OUTOFMEMORY;
  519.     else if FAILED(hr)
  520.     {
  521.         delete *ppEnum;
  522.         *ppEnum = 0;
  523.     }
  524.     return hr;
  525. }
  526.  
  527. STDMETHODIMP CAMovie::EnumPinsOut( IEnumPins ** ppEnum )
  528. {
  529.     HRESULT hr = NOERROR;
  530.     *ppEnum = new CImpIEnumPinsOutOverGraph( pGB, &hr );
  531.     if (!*ppEnum) hr = E_OUTOFMEMORY;
  532.     else if FAILED(hr)
  533.     {
  534.         delete *ppEnum;
  535.         *ppEnum = 0;
  536.     }
  537.     return hr;
  538. }
  539.  
  540.  
  541. // Protected methods
  542.  
  543. // #include <iostream.h>
  544. // #include <SampIOS.h>
  545.  
  546. // Disconnect all pins.  If a filter has no pins, remove it completely
  547. // This is to part-destroy a filter graph, leaving only those filters
  548. // that may be usefult for rendering a file or pin after this function
  549. // has been called.
  550. HRESULT CAMovie::DisconnectAllAndRemoveIsolates()
  551. {
  552.     // cout << "Pre DisconnectAllAndRemoveIsolates()\n" << pGB << endl;
  553.     HRESULT  hr;
  554.  
  555.     IEnumFilters * piEnumFilters;
  556.     hr = EnumFilters( &piEnumFilters );
  557.     if SUCCEEDED(hr)
  558.     {
  559.         CGenericList<IPin>    PinList("List of pins to be disconnected");
  560.         CGenericList<IFilter> FilterList("List of filters to be removed");
  561.         IFilter * piFilter;
  562.         IPin * piPin;
  563.         while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
  564.         {
  565.             BOOL connected = FALSE, connectable = FALSE;
  566.             IEnumPins * piEnumPins;
  567.             hr = piFilter->EnumPins( &piEnumPins );
  568.             if SUCCEEDED(hr)
  569.             {
  570.                 while ( piEnumPins->Next(1, &piPin, 0) == NOERROR )
  571.                 {
  572.                     connectable = TRUE;
  573.                     IPin * piPinConnectedTo;
  574.                     piPin->ConnectedTo( &piPinConnectedTo );
  575.                     if (piPinConnectedTo)
  576.                     {
  577.                         PinList.AddTail( piPin );
  578.                         piPinConnectedTo->Release();
  579.                     }
  580.                     else piPin->Release();
  581.                 }
  582.                 piEnumPins->Release();
  583.             }
  584.             if (!connectable)   FilterList.AddTail( piFilter );
  585.             else                piFilter->Release();
  586.         }
  587.         piEnumFilters->Release();
  588.         while ( piPin = PinList.RemoveHead() )
  589.         {
  590.             hr = Disconnect( piPin );
  591.             piPin->Release();
  592.         }
  593.         while ( piFilter = FilterList.RemoveHead() )
  594.         {
  595.             hr = RemoveFilter( piFilter );
  596.             piFilter->Release();
  597.         }
  598.     }
  599.     // cout << "Post DisconnectAllAndRemoveIsolates()\n" << pGB << endl;
  600.     return hr;
  601. }
  602.  
  603. // For all filters in graph, if the filter has pins, and all are unconnected,
  604. // then remove the filter from the graph.
  605. HRESULT CAMovie::RemoveAllUnconnected()
  606. {
  607.     // cout << "Pre RemoveAllUnconnected()\n" << pGB << endl;
  608.     HRESULT  hr;
  609.  
  610.     IEnumFilters * piEnumFilters;
  611.     hr = EnumFilters( &piEnumFilters );
  612.     if SUCCEEDED(hr)
  613.     {
  614.         CGenericList<IFilter> FilterList("List of filters to be removed");
  615.         IFilter * piFilter;
  616.         while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
  617.         {
  618.             BOOL connected = FALSE, connectable = FALSE;
  619.             IEnumPins * piEnumPins;
  620.             hr = piFilter->EnumPins( &piEnumPins );
  621.             if SUCCEEDED(hr)
  622.             {
  623.                 IPin * piPin;
  624.                 while ( !connected && piEnumPins->Next(1, &piPin, 0) == NOERROR )
  625.                 {
  626.                     connectable = TRUE;
  627.                     IPin * piPinConnectedTo;
  628.                     piPin->ConnectedTo( &piPinConnectedTo );
  629.                     if (piPinConnectedTo)
  630.                     {
  631.                         connected = TRUE;
  632.                         piPinConnectedTo->Release();
  633.                     }
  634.                     piPin->Release();
  635.                 }
  636.                 piEnumPins->Release();
  637.             }
  638.             if (connectable && !connected)  FilterList.AddTail( piFilter );
  639.             else                            piFilter->Release();
  640.         }
  641.         piEnumFilters->Release();
  642.         while ( piFilter = FilterList.RemoveHead() )
  643.         {
  644.             hr = RemoveFilter( piFilter );
  645.             piFilter->Release();
  646.         }
  647.     }
  648.     // cout << "Post RemoveAllUnconnected()\n" << pGB << endl;
  649.     return hr;
  650. }
  651.  
  652. // exported entry points for registration and
  653. // unregistration (in this case they only call
  654. // through to default implmentations).
  655. //
  656. HRESULT DllRegisterServer()
  657. {
  658.   return AMovieDllRegisterServer();
  659. }
  660.  
  661. HRESULT DllUnregisterServer()
  662. {
  663.   return AMovieDllUnregisterServer();
  664. }
  665.