home *** CD-ROM | disk | FTP | other *** search
- //==========================================================================;
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
- // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
- // PURPOSE.
- //
- // Copyright (c) 1992 - 1996 Microsoft Corporation. All Rights Reserved.
- //
- //--------------------------------------------------------------------------;
-
- #include <streams.h>
- #include "Ext_Enum.h"
-
- class CAMovie : public IAMovie, public CUnknown
- {
- private:
- IGraphBuilder * pGB;
- IMediaControl * pMC;
- IMediaEvent * pME;
- IMediaPosition * pMP;
-
- protected:
- ~CAMovie();
- CAMovie(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr);
-
- // Disconnect all pins. If a filter has no pins, remove it completely
- // This is to part-destroy a filter graph, leaving only those filters
- // that may be usefult for rendering a file or pin after this function
- // has been called.
- HRESULT DisconnectAllAndRemoveIsolates();
-
- // For all filters in graph, if the filter has pins, and all are unconnected,
- // then remove the filter from the graph.
- HRESULT RemoveAllUnconnected();
-
- public:
- DECLARE_IUNKNOWN
-
- static CUnknown *CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
-
- STDMETHODIMP NonDelegatingQueryInterface(REFIID iid, void ** ppv);
-
- // IFilterGraph
-
- // Add a filter to the graph and name it with *pName.
- // If the name is not unique, The request will fail.
- // The Filter graph will call the JoinFilterGraph
- // member function of the filter to inform it.
- // This must be called before attempting Connect, ConnectDirect or Render
- // for pins of the filter.
-
- STDMETHODIMP AddFilter
- ( IFilter * pFilter,
- LPCWSTR pName
- );
-
- // Remove a filter from the graph. The filter graph implementation
- // will inform the filter that it is being removed.
-
- STDMETHODIMP RemoveFilter
- ( IFilter * pFilter
- );
-
- // Set *ppEnum to be an enumerator for all filters in the graph.
-
- STDMETHODIMP EnumFilters
- ( IEnumFilters **ppEnum
- );
-
- // Set *ppFilter to be the filter which was added with the name *pName
- // Will fail and set *ppFilter to NULL if the name is not in this graph.
-
- STDMETHODIMP FindFilterByName
- ( LPCWSTR pName,
- IFilter ** ppFilter
- );
-
- //==========================================================================
- // Low level connection functions
- //==========================================================================
-
- // Connect these two pins directly (i.e. without intervening filters)
- // the media type is optional, and may be partially specified (that is
- // the subtype and/or format type may be GUID_NULL). See IPin::Connect
- // for details of the media type parameter.
- STDMETHODIMP ConnectDirect
- ( IPin * ppinOut, // the output pin
- IPin * ppinIn, // the input pin
- const AM_MEDIA_TYPE* pmt // optional mediatype
- );
-
- // On a separate thread (which will not hold any relevant locks)
- // Break the connection that this pin has and reconnect it to the
- // same other pin.
-
- STDMETHODIMP Reconnect
- ( IPin * ppin // the pin to disconnect and reconnect
- );
-
- // Disconnect this pin, if connected. Successful no-op if not connected.
-
- STDMETHODIMP Disconnect
- ( IPin * ppin
- );
-
- //==========================================================================
- // intelligent connectivity - now in IGraphBuilder, axextend.idl
- //==========================================================================
-
- //==========================================================================
- // Whole graph functions
- //==========================================================================
-
- // Once a graph is built, it can behave as a (composite) filter.
- // To control this filter, QueryInterface for IMediaFilter.
-
- // The filtergraph will by default ensure that the graph has a sync source
- // when it is made to Run. SetSyncSource(NULL) will prevent that and allow
- // all the filters to run unsynchronised until further notice.
- // SetDefaultSyncSource will set the default sync source (the same as would
- // have been set by default on the first call to Run).
- STDMETHODIMP SetDefaultSyncSource(void);
-
-
-
- // IGraphBuilder
-
- // Connect these two pins directly or indirectly, using transform filters
- // if necessary.
-
- STDMETHODIMP Connect
- ( IPin * ppinOut, // the output pin
- IPin * ppinIn // the input pin
- );
-
- // Connect this output pin directly or indirectly, using transform filters
- // if necessary to something that will render it.
-
- STDMETHODIMP Render
- ( IPin * ppinOut // the output pin
- );
-
- // This pair of methods are a cross between the IGraphBuilder ones and the IMediaControl ones,
- // unfortunate perhaps, but they do make the nicest C / C++ interfaces .
-
- // adds and connects filters needed to play the specified file
- STDMETHODIMP RenderFile( LPCWSTR strFilename );
-
- // adds to the graph the source filter that can read this file,
- // and returns an IFilterInfo object for it
- STDMETHODIMP AddSourceFilter( LPCWSTR strFilename, IFilter ** ppUnk);
-
-
- // IMediaControl methods
- STDMETHODIMP Run();
- STDMETHODIMP Pause();
- STDMETHODIMP Stop();
-
- //returns the state. same semantics as IMediaFilter::GetState
- STDMETHODIMP GetState(
- LONG msTimeout,
- FILTER_STATE* pfs);
-
- // IMediaEvent
-
- // get back the event handle. This is manual-reset
- // (don't - it's reset by the event mechanism) and remains set
- // when events are queued, and reset when the queue is empty.
- STDMETHODIMP GetEventHandle(
- HEVENT * hEvent);
-
- // remove the next event notification from the head of the queue and
- // return it. Waits up to msTimeout millisecs if there are no events.
- // if a timeout occurs without any events, this method will return
- // E_ABORT, and the value of the event code and other parameters
- // is undefined.
- STDMETHODIMP GetEvent(
- long * lEventCode,
- long * lParam1,
- long * lParam2,
- long msTimeout
- );
-
- // Calls GetEvent repeatedly discarding events until it finds a
- // completion event (EC_COMPLETE, EC_ERRORABORT, or EC_USERABORT).
- // The completion event is removed from the queue and returned
- // in pEvCode. Note that the object is still in running mode until
- // a Pause or Stop call is made.
- // If the timeout occurs, *pEvCode will be 0 and E_ABORT will be
- // returned.
- STDMETHODIMP WaitForCompletion(
- long msTimeout,
- long * pEvCode);
-
- // cancels any system handling of the specified event code
- // and ensures that the events are passed straight to the application
- // (via GetEvent) and not handled. A good example of this is
- // EC_REPAINT: default handling for this ensures the painting of the
- // window and does not get posted to the app.
- STDMETHODIMP CancelDefaultHandling(
- long lEvCode);
-
- // restore the normal system default handling that may have been
- // cancelled by CancelDefaultHandling().
- STDMETHODIMP RestoreDefaultHandling( long lEvCode);
-
-
- // IMediaPosition
- // properties
- STDMETHODIMP get_Duration(
- REFTIME* plength);
-
- STDMETHODIMP put_CurrentPosition(
- REFTIME llTime);
-
- STDMETHODIMP get_CurrentPosition(
- REFTIME* pllTime);
-
- STDMETHODIMP get_StopTime(
- REFTIME* pllTime);
-
- STDMETHODIMP put_StopTime(
- REFTIME llTime);
-
- STDMETHODIMP get_PrerollTime(
- REFTIME* pllTime);
- STDMETHODIMP put_PrerollTime(
- REFTIME llTime);
-
- STDMETHODIMP put_Rate(
- double dRate);
- STDMETHODIMP get_Rate(
- double * pdRate);
-
- /* New methods */
-
- // Remove all filters
- STDMETHODIMP RemoveAllFilters();
-
- // If the filter graph can be Run to completion, run it and wait for it to complete
- STDMETHODIMP Play();
- // As above, but RenderNewFile first
- STDMETHODIMP PlayFile( LPCWSTR strFilename );
-
- // Render all unconnected output pins
- STDMETHODIMP RenderAll();
- // Render supplied files "as if" the filter graoh were first emptied
- STDMETHODIMP RenderNewFile( LPCWSTR strFilename );
-
- STDMETHODIMP EnumFiltersByInterface( REFIID iid, IEnumFilters ** pEnumFilters );
- // Enum pins over the entire graph
- STDMETHODIMP EnumPins( IEnumPins ** ppEnum );
- STDMETHODIMP EnumPinsIn( IEnumPins ** ppEnum );
- STDMETHODIMP EnumPinsOut( IEnumPins ** ppEnum );
- };
-
-
-
- CFactoryTemplate g_Templates[]=
- { {L"ActiveMovie Sample PID", &CLSID_AMovie, CAMovie::CreateInstance},
- };
- int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
-
-
- CAMovie::~CAMovie()
- { /* nothing to do */ }
-
- CAMovie::CAMovie(TCHAR *pName, LPUNKNOWN pUnk, HRESULT *phr)
- : CUnknown( pName, pUnk, phr )
- , pGB(0), pMC(0), pME(0), pMP(0)
- {
- if (!pUnk) *phr = VFW_E_NEED_OWNER;
- else if SUCCEEDED(*phr)
- {
- *phr = pUnk->QueryInterface( IID_IGraphBuilder, reinterpret_cast<void**>(&pGB) );
- if SUCCEEDED(*phr)
- {
- pGB->Release();
- *phr = pUnk->QueryInterface( IID_IMediaControl, reinterpret_cast<void**>(&pMC) );
- if SUCCEEDED(*phr)
- {
- pMC->Release();
- *phr = pUnk->QueryInterface( IID_IMediaEvent, reinterpret_cast<void**>(&pME) );
- if SUCCEEDED(*phr)
- {
- pME->Release();
- *phr = pUnk->QueryInterface( IID_IMediaPosition, reinterpret_cast<void**>(&pMP) );
- if SUCCEEDED(*phr) pMP->Release();
- }
- }
- }
- }
- }
-
- CUnknown * CAMovie::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
- {
- CUnknown * result = 0;
- result = new CAMovie( NAME("IAMovie Class"), pUnk, phr );
- if ( !result ) *phr = E_OUTOFMEMORY;
- return result;
- }
-
- STDMETHODIMP CAMovie::NonDelegatingQueryInterface(REFIID iid, void ** ppv)
- {
- if ( iid == IID_IAMovie )
- {
- return GetInterface(static_cast<IAMovie *>(this), ppv );
- }
- else
- {
- return CUnknown::NonDelegatingQueryInterface(iid, ppv);
- }
- }
-
-
- // IFilterGraph (pGB)
- STDMETHODIMP CAMovie::AddFilter( IFilter * pFilter, LPCWSTR pName )
- { return pGB->AddFilter( pFilter, pName ); }
- STDMETHODIMP CAMovie::RemoveFilter( IFilter * pFilter )
- { return pGB->RemoveFilter( pFilter ); }
- STDMETHODIMP CAMovie::EnumFilters( IEnumFilters **ppEnum )
- { return pGB->EnumFilters( ppEnum ); }
- STDMETHODIMP CAMovie::FindFilterByName( LPCWSTR pName, IFilter ** ppFilter )
- { return pGB->FindFilterByName( pName, ppFilter ); }
- STDMETHODIMP CAMovie::ConnectDirect( IPin * ppinOut, IPin * ppinIn, const AM_MEDIA_TYPE* pmt )
- { return pGB->ConnectDirect( ppinOut, ppinIn, pmt ); }
- STDMETHODIMP CAMovie::Reconnect( IPin * ppin )
- { return pGB->Reconnect( ppin ); }
- STDMETHODIMP CAMovie::Disconnect( IPin * ppin )
- { return pGB->Disconnect( ppin ); }
- STDMETHODIMP CAMovie::SetDefaultSyncSource( )
- { return pGB->SetDefaultSyncSource( ); }
-
-
- // IGraphBuilder (pGB)
- STDMETHODIMP CAMovie::Connect( IPin * ppinOut, IPin * ppinIn )
- { return pGB->Connect( ppinOut, ppinIn ); }
- STDMETHODIMP CAMovie::Render( IPin * ppinOut )
- { return pGB->Render( ppinOut ); }
-
-
- // This pair of methods are a cross between the IGraphBuilder ones and the IMediaControl ones,
- // unfortunate perhaps, but they do make the nicest C / C++ interfaces .
- STDMETHODIMP CAMovie::AddSourceFilter( LPCWSTR strFilename, IFilter ** ppUnk )
- {
- const LPWSTR fn = const_cast<LPWSTR>(strFilename);
- return pGB->AddSourceFilter( fn, fn, ppUnk );
- }
-
- STDMETHODIMP CAMovie::RenderFile( LPCWSTR strFilename )
- {
- const LPWSTR fn = const_cast<LPWSTR>(strFilename);
- return pGB->RenderFile( fn, fn );
- }
-
-
- // IMediaControl (pMC)
- STDMETHODIMP CAMovie::Run( )
- { return pMC->Run( ); }
- STDMETHODIMP CAMovie::Pause( )
- { return pMC->Pause( ); }
- STDMETHODIMP CAMovie::Stop( )
- { return pMC->Stop( ); }
- STDMETHODIMP CAMovie::GetState( LONG msTimeout, FILTER_STATE* pfs )
- { return pMC->GetState( msTimeout, (long *)pfs ); }
-
-
-
- // IMediaEvent (pME)
- STDMETHODIMP CAMovie::GetEventHandle( HEVENT * hEvent )
- { return pME->GetEventHandle( (long *)hEvent ); }
- STDMETHODIMP CAMovie::GetEvent( long * lEventCode, long * lParam1, long * lParam2, long msTimeout )
- { return pME->GetEvent( lEventCode, lParam1, lParam2, msTimeout ); }
- STDMETHODIMP CAMovie::WaitForCompletion( long msTimeout, long * pEvCode )
- { return pME->WaitForCompletion( msTimeout, pEvCode ); }
- STDMETHODIMP CAMovie::CancelDefaultHandling( long lEvCode )
- { return pME->CancelDefaultHandling( lEvCode ); }
- STDMETHODIMP CAMovie::RestoreDefaultHandling( long lEvCode )
- { return pME->RestoreDefaultHandling( lEvCode ); }
-
-
- // IMediaPosition (pMP )
- STDMETHODIMP CAMovie::get_Duration( REFTIME* plength )
- { return pMP->get_Duration( plength ); }
- STDMETHODIMP CAMovie::put_CurrentPosition( REFTIME llTime )
- { return pMP->put_CurrentPosition( llTime ); }
- STDMETHODIMP CAMovie::get_CurrentPosition( REFTIME* pllTime )
- { return pMP->get_CurrentPosition( pllTime ); }
- STDMETHODIMP CAMovie::get_StopTime( REFTIME* pllTime )
- { return pMP->get_StopTime( pllTime ); }
- STDMETHODIMP CAMovie::put_StopTime( REFTIME llTime )
- { return pMP->put_StopTime( llTime ); }
- STDMETHODIMP CAMovie::get_PrerollTime( REFTIME* pllTime )
- { return pMP->get_PrerollTime( pllTime ); }
- STDMETHODIMP CAMovie::put_PrerollTime( REFTIME llTime )
- { return pMP->put_PrerollTime( llTime ); }
- STDMETHODIMP CAMovie::put_Rate( double dRate )
- { return pMP->put_Rate( dRate ); }
- STDMETHODIMP CAMovie::get_Rate( double * pdRate )
- { return pMP->get_Rate( pdRate ); }
-
-
-
- // New methods
-
- // Remove all filters
- STDMETHODIMP CAMovie::RemoveAllFilters()
- {
- HRESULT hr;
-
- IEnumFilters * piEnumFilters;
- hr = EnumFilters( &piEnumFilters );
- if SUCCEEDED(hr)
- {
- CGenericList<IFilter> FilterList("List of filters to be removed");
-
- IFilter * piFilter;
- while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
- {
- FilterList.AddTail( piFilter );
- }
- piEnumFilters->Release();
- while ( piFilter = FilterList.RemoveHead() )
- {
- hr = RemoveFilter( piFilter );
- piFilter->Release();
- }
- }
- return hr;
- }
-
- // If the filter graph can be Run to completion, run it and wait for it to complete
- STDMETHODIMP CAMovie::Play()
- {
- HRESULT hr;
- REFTIME duration;
- hr = get_Duration( &duration );
- if ( SUCCEEDED( hr ) && duration > 0 )
- {
- hr = Run();
- if SUCCEEDED(hr)
- {
- long evCode;
- WaitForCompletion( INFINITE, &evCode );
- }
- Stop();
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::PlayFile( LPCWSTR strFilename )
- {
- HRESULT hr;
- hr = RenderNewFile( strFilename );
- if SUCCEEDED(hr)
- {
- hr = Play();
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::RenderAll( )
- {
- HRESULT hr = NOERROR;
- CImpIEnumPinsOutOverGraph EnumOutPins( this, &hr );
- if SUCCEEDED(hr)
- {
- IPin * piPin;
-
- while ( EnumOutPins.Next( 1, &piPin, 0 ) == NOERROR )
- {
- Render( piPin );
- }
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::RenderNewFile( LPCWSTR strFilename )
- {
- HRESULT hr;
- DisconnectAllAndRemoveIsolates();
- hr = RenderFile( strFilename );
- RemoveAllUnconnected();
- return hr;
- }
-
- STDMETHODIMP CAMovie::EnumFiltersByInterface( REFIID iid, IEnumFilters ** ppEnum )
- {
- HRESULT hr = NOERROR;
- *ppEnum = new CImpIEnumFilters( pGB, iid );
- if (!*ppEnum) hr = E_OUTOFMEMORY;
- else if FAILED(hr)
- {
- delete *ppEnum;
- *ppEnum = 0;
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::EnumPins( IEnumPins ** ppEnum )
- {
- HRESULT hr = NOERROR;
- *ppEnum = new CImpIEnumPinsOverGraph( pGB, &hr );
- if (!*ppEnum) hr = E_OUTOFMEMORY;
- else if FAILED(hr)
- {
- delete *ppEnum;
- *ppEnum = 0;
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::EnumPinsIn( IEnumPins ** ppEnum )
- {
- HRESULT hr = NOERROR;
- *ppEnum = new CImpIEnumPinsInOverGraph( pGB, &hr );
- if (!*ppEnum) hr = E_OUTOFMEMORY;
- else if FAILED(hr)
- {
- delete *ppEnum;
- *ppEnum = 0;
- }
- return hr;
- }
-
- STDMETHODIMP CAMovie::EnumPinsOut( IEnumPins ** ppEnum )
- {
- HRESULT hr = NOERROR;
- *ppEnum = new CImpIEnumPinsOutOverGraph( pGB, &hr );
- if (!*ppEnum) hr = E_OUTOFMEMORY;
- else if FAILED(hr)
- {
- delete *ppEnum;
- *ppEnum = 0;
- }
- return hr;
- }
-
-
- // Protected methods
-
- // #include <iostream.h>
- // #include <SampIOS.h>
-
- // Disconnect all pins. If a filter has no pins, remove it completely
- // This is to part-destroy a filter graph, leaving only those filters
- // that may be usefult for rendering a file or pin after this function
- // has been called.
- HRESULT CAMovie::DisconnectAllAndRemoveIsolates()
- {
- // cout << "Pre DisconnectAllAndRemoveIsolates()\n" << pGB << endl;
- HRESULT hr;
-
- IEnumFilters * piEnumFilters;
- hr = EnumFilters( &piEnumFilters );
- if SUCCEEDED(hr)
- {
- CGenericList<IPin> PinList("List of pins to be disconnected");
- CGenericList<IFilter> FilterList("List of filters to be removed");
- IFilter * piFilter;
- IPin * piPin;
- while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
- {
- BOOL connected = FALSE, connectable = FALSE;
- IEnumPins * piEnumPins;
- hr = piFilter->EnumPins( &piEnumPins );
- if SUCCEEDED(hr)
- {
- while ( piEnumPins->Next(1, &piPin, 0) == NOERROR )
- {
- connectable = TRUE;
- IPin * piPinConnectedTo;
- piPin->ConnectedTo( &piPinConnectedTo );
- if (piPinConnectedTo)
- {
- PinList.AddTail( piPin );
- piPinConnectedTo->Release();
- }
- else piPin->Release();
- }
- piEnumPins->Release();
- }
- if (!connectable) FilterList.AddTail( piFilter );
- else piFilter->Release();
- }
- piEnumFilters->Release();
- while ( piPin = PinList.RemoveHead() )
- {
- hr = Disconnect( piPin );
- piPin->Release();
- }
- while ( piFilter = FilterList.RemoveHead() )
- {
- hr = RemoveFilter( piFilter );
- piFilter->Release();
- }
- }
- // cout << "Post DisconnectAllAndRemoveIsolates()\n" << pGB << endl;
- return hr;
- }
-
- // For all filters in graph, if the filter has pins, and all are unconnected,
- // then remove the filter from the graph.
- HRESULT CAMovie::RemoveAllUnconnected()
- {
- // cout << "Pre RemoveAllUnconnected()\n" << pGB << endl;
- HRESULT hr;
-
- IEnumFilters * piEnumFilters;
- hr = EnumFilters( &piEnumFilters );
- if SUCCEEDED(hr)
- {
- CGenericList<IFilter> FilterList("List of filters to be removed");
- IFilter * piFilter;
- while ( piEnumFilters->Next(1, &piFilter, 0) == NOERROR )
- {
- BOOL connected = FALSE, connectable = FALSE;
- IEnumPins * piEnumPins;
- hr = piFilter->EnumPins( &piEnumPins );
- if SUCCEEDED(hr)
- {
- IPin * piPin;
- while ( !connected && piEnumPins->Next(1, &piPin, 0) == NOERROR )
- {
- connectable = TRUE;
- IPin * piPinConnectedTo;
- piPin->ConnectedTo( &piPinConnectedTo );
- if (piPinConnectedTo)
- {
- connected = TRUE;
- piPinConnectedTo->Release();
- }
- piPin->Release();
- }
- piEnumPins->Release();
- }
- if (connectable && !connected) FilterList.AddTail( piFilter );
- else piFilter->Release();
- }
- piEnumFilters->Release();
- while ( piFilter = FilterList.RemoveHead() )
- {
- hr = RemoveFilter( piFilter );
- piFilter->Release();
- }
- }
- // cout << "Post RemoveAllUnconnected()\n" << pGB << endl;
- return hr;
- }
-
- // exported entry points for registration and
- // unregistration (in this case they only call
- // through to default implmentations).
- //
- HRESULT DllRegisterServer()
- {
- return AMovieDllRegisterServer();
- }
-
- HRESULT DllUnregisterServer()
- {
- return AMovieDllUnregisterServer();
- }
-