/*
 * Copyright (C) 2002 Robert Shearman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#define CHARS_IN_GUID 39
cpp_quote("#define CHARS_IN_GUID 39")

/* GetTimeFormat is defined in winnls.h as
 * either the W or A suffixed version */
cpp_quote("#undef GetTimeFormat")

typedef struct _AMMediaType
{
    GUID       majortype;
    GUID       subtype;
    BOOL       bFixedSizeSamples;
    BOOL       bTemporalCompression;
    ULONG      lSampleSize;
    GUID       formattype;
    IUnknown * pUnk;
    ULONG      cbFormat;
    [size_is(cbFormat)] BYTE * pbFormat;
} AM_MEDIA_TYPE;

typedef enum _PinDirection
{
    PINDIR_INPUT,
    PINDIR_OUTPUT
} PIN_DIRECTION;

#define MAX_PIN_NAME    128
#define MAX_FILTER_NAME 128
cpp_quote("#define MAX_PIN_NAME    128")
cpp_quote("#define MAX_FILTER_NAME 128")

cpp_quote("#ifndef REFERENCE_TIME_DEFINED")
cpp_quote("#define REFERENCE_TIME_DEFINED")
typedef LONGLONG REFERENCE_TIME;
cpp_quote("#endif")

cpp_quote("#ifndef REFTIME_DEFINED")
cpp_quote("#define REFTIME_DEFINED")
typedef DOUBLE REFTIME;
cpp_quote("#endif")

typedef DWORD_PTR HSEMAPHORE;
typedef DWORD_PTR HEVENT;

typedef struct _AllocatorProperties
{
    long cBuffers;
    long cbBuffer;
    long cbAlign;
    long cbPrefix;
} ALLOCATOR_PROPERTIES;

interface IAMovieSetup;
interface IEnumFilters;
interface IEnumMediaTypes;
interface IEnumPins;
interface IBaseFilter;
interface IFilterGraph;
interface IMediaFilter;
interface IMediaSample;
interface IMemAllocator;
interface IMemAllocatorCallbackTemp;
interface IMemAllocatorNotifyCallbackTemp;
interface IMemInputPin;
interface IPin;
interface IReferenceClock;

[
object,
uuid(56a86891-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IPin : IUnknown
{
    typedef struct _PinInfo
    {
        IBaseFilter *pFilter;
        PIN_DIRECTION dir;
        WCHAR achName[MAX_PIN_NAME];
    } PIN_INFO;

    HRESULT Connect(
        [in] IPin * pReceivePin,
        [in] const AM_MEDIA_TYPE * pmt);

    HRESULT ReceiveConnection(
        [in] IPin * pConnector,
        [in] const AM_MEDIA_TYPE *pmt);

    HRESULT Disconnect(void);

    HRESULT ConnectedTo(
        [out] IPin **pPin);

    HRESULT ConnectionMediaType(
        [out] AM_MEDIA_TYPE *pmt);

    HRESULT QueryPinInfo(
        [out] PIN_INFO * pInfo);

    HRESULT QueryDirection(
        [out] PIN_DIRECTION *pPinDir);

    HRESULT QueryId(
        [out] LPWSTR * Id);

    HRESULT QueryAccept(
        [in] const AM_MEDIA_TYPE *pmt);

    HRESULT EnumMediaTypes(
        [out] IEnumMediaTypes **ppEnum);

    HRESULT QueryInternalConnections(
        [out] IPin* *apPin,
        [in, out] ULONG *nPin);

    HRESULT EndOfStream(void);

    HRESULT BeginFlush(void);

    HRESULT EndFlush(void);
    HRESULT NewSegment(
        [in] REFERENCE_TIME tStart,
        [in] REFERENCE_TIME tStop,
        [in] double dRate);
}

typedef IPin *PPIN;

[
object,
uuid(56a86892-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IEnumPins : IUnknown
{

    HRESULT Next(
        [in] ULONG cPins,
        [out, size_is(cPins)] IPin ** ppPins,
        [out] ULONG * pcFetched);

    HRESULT Skip(
        [in] ULONG cPins);

    HRESULT Reset(void);

    HRESULT Clone(
        [out] IEnumPins **ppEnum);
}

typedef IEnumPins *PENUMPINS;

[
object,
uuid(89c31040-846b-11ce-97d3-00aa0055595a),
pointer_default(unique)
]
interface IEnumMediaTypes : IUnknown
{
    HRESULT Next(
        [in] ULONG cMediaTypes,
        [out, size_is(cMediaTypes)]
             AM_MEDIA_TYPE ** ppMediaTypes,
        [out] ULONG * pcFetched
    );

    HRESULT Skip(
        [in] ULONG cMediaTypes);

    HRESULT Reset(void);

    HRESULT Clone(
        [out] IEnumMediaTypes **ppEnum
    );
}

typedef IEnumMediaTypes *PENUMMEDIATYPES;

[
object,
uuid(56a8689f-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IFilterGraph : IUnknown
{
    HRESULT AddFilter(
        [in] IBaseFilter * pFilter,
        [in, string] LPCWSTR pName);

    HRESULT RemoveFilter(
        [in] IBaseFilter * pFilter);

    HRESULT EnumFilters(
        [out] IEnumFilters **ppEnum);

    HRESULT FindFilterByName(
        [in, string] LPCWSTR pName,
        [out] IBaseFilter ** ppFilter);

    HRESULT ConnectDirect(
        [in] IPin * ppinOut,
        [in] IPin * ppinIn,
        [in, unique] const AM_MEDIA_TYPE* pmt);

    HRESULT Reconnect(
        [in] IPin * ppin);

    HRESULT Disconnect(
        [in] IPin * ppin);

    HRESULT SetDefaultSyncSource(void);
}

typedef IFilterGraph *PFILTERGRAPH;

[
object,
uuid(56a86893-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IEnumFilters : IUnknown
{
    HRESULT Next(
        [in]  ULONG cFilters,
        [out] IBaseFilter ** ppFilter,
        [out] ULONG * pcFetched);


    HRESULT Skip(
        [in] ULONG cFilters);


    HRESULT Reset(void);


    HRESULT Clone(
        [out] IEnumFilters **ppEnum);
}

typedef IEnumFilters *PENUMFILTERS;

[
object,
uuid(56a86899-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaFilter : IPersist
{
    typedef enum _FilterState
    {
        State_Stopped,
        State_Paused,
        State_Running
    } FILTER_STATE;

    HRESULT Stop(void);
    HRESULT Pause(void);

    HRESULT Run(REFERENCE_TIME tStart);

    HRESULT GetState(
        [in] DWORD dwMilliSecsTimeout,
        [out] FILTER_STATE *State);

    HRESULT SetSyncSource(
        [in] IReferenceClock * pClock);

    HRESULT GetSyncSource(
        [out] IReferenceClock ** pClock);
}

typedef IMediaFilter *PMEDIAFILTER;

[
object,
uuid(56a86895-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBaseFilter : IMediaFilter
{
    typedef struct _FilterInfo
    {
        WCHAR achName[MAX_FILTER_NAME];
        IFilterGraph * pGraph;
    } FILTER_INFO;

    HRESULT EnumPins(
        [out] IEnumPins ** ppEnum);

    HRESULT FindPin(
        [in, string] LPCWSTR Id,
        [out] IPin ** ppPin);

    HRESULT QueryFilterInfo(
        [out] FILTER_INFO * pInfo);

    HRESULT JoinFilterGraph(
        [in] IFilterGraph * pGraph,
        [in, string] LPCWSTR pName);

    HRESULT QueryVendorInfo(
        [out, string] LPWSTR* pVendorInfo);
}

typedef IBaseFilter *PFILTER;

[
object,
uuid(56a86897-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IReferenceClock : IUnknown
{
    HRESULT GetTime(
        [out] REFERENCE_TIME *pTime);

    HRESULT AdviseTime(
        [in] REFERENCE_TIME baseTime,
        [in] REFERENCE_TIME streamTime,
        [in] HEVENT hEvent,
        [out] DWORD_PTR * pdwAdviseCookie);

    HRESULT AdvisePeriodic(
        [in] REFERENCE_TIME startTime,
        [in] REFERENCE_TIME periodTime,
        [in] HSEMAPHORE hSemaphore,
        [out] DWORD_PTR * pdwAdviseCookie);

    HRESULT Unadvise(
        [in] DWORD_PTR dwAdviseCookie);
}

typedef IReferenceClock *PREFERENCECLOCK;

/*
[
object,
uuid(36b73885-c2c8-11cf-8b46-00805f6cef60),
pointer_default(unique)
]
interface IReferenceClock2 : IReferenceClock
{
}

typedef IReferenceClock2 *PREFERENCECLOCK2;

*/

[
local,
object,
uuid(56a8689a-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaSample : IUnknown
{
    HRESULT GetPointer([out] BYTE ** ppBuffer);

    long GetSize(void);

    HRESULT GetTime(
        [out] REFERENCE_TIME * pTimeStart,
        [out] REFERENCE_TIME * pTimeEnd);

    HRESULT SetTime(
        [in] REFERENCE_TIME * pTimeStart,
        [in] REFERENCE_TIME * pTimeEnd);

    HRESULT IsSyncPoint(void);

    HRESULT SetSyncPoint(BOOL bIsSyncPoint);

    HRESULT IsPreroll(void);

    HRESULT SetPreroll(BOOL bIsPreroll);

    LONG GetActualDataLength(void);

    HRESULT SetActualDataLength(LONG length);

    HRESULT GetMediaType(AM_MEDIA_TYPE **ppMediaType);

    HRESULT SetMediaType(AM_MEDIA_TYPE *pMediaType);

    HRESULT IsDiscontinuity(void);

    HRESULT SetDiscontinuity(BOOL bDiscontinuity);

    HRESULT GetMediaTime(
        [out] LONGLONG * pTimeStart,
        [out] LONGLONG * pTimeEnd);

    HRESULT SetMediaTime(
        [in] LONGLONG * pTimeStart,
        [in] LONGLONG * pTimeEnd);
}

typedef IMediaSample *PMEDIASAMPLE;

enum tagAM_SAMPLE_PROPERTY_FLAGS
{
       AM_SAMPLE_SPLICEPOINT        = 0x01,
       AM_SAMPLE_PREROLL            = 0x02,
       AM_SAMPLE_DATADISCONTINUITY  = 0x04,
       AM_SAMPLE_TYPECHANGED        = 0x08,
       AM_SAMPLE_TIMEVALID          = 0x10,
       AM_SAMPLE_TIMEDISCONTINUITY  = 0x40,
       AM_SAMPLE_FLUSH_ON_PAUSE     = 0x80,
       AM_SAMPLE_STOPVALID          = 0x100,
       AM_SAMPLE_ENDOFSTREAM        = 0x200,
       AM_STREAM_MEDIA              = 0,
       AM_STREAM_CONTROL            = 1
};

typedef struct tagAM_SAMPLE2_PROPERTIES
{
    DWORD    cbData;
    DWORD    dwTypeSpecificFlags;
    DWORD    dwSampleFlags;
    LONG     lActual;
    REFERENCE_TIME tStart;
    REFERENCE_TIME tStop;
    DWORD    dwStreamId;
    AM_MEDIA_TYPE *pMediaType;
    BYTE    *pbBuffer;
    LONG     cbBuffer;
} AM_SAMPLE2_PROPERTIES;

[
        local,
        object,
        uuid(36b73884-c2c8-11cf-8b46-00805f6cef60),
        pointer_default(unique)
]
interface IMediaSample2 : IMediaSample
{
    HRESULT GetProperties(
        [in] DWORD cbProperties,
        [out, size_is(cbProperties)] BYTE * pbProperties
    );

    HRESULT SetProperties(
        [in] DWORD cbProperties,
        [in, size_is(cbProperties)] const BYTE * pbProperties
    );
}

typedef IMediaSample2 *PMEDIASAMPLE2;

#define AM_GBF_PREVFRAMESKIPPED 1
#define AM_GBF_NOTASYNCPOINT    2
cpp_quote("#define AM_GBF_PREVFRAMESKIPPED 1")
cpp_quote("#define AM_GBF_NOTASYNCPOINT 2")

cpp_quote("#define AM_GBF_NOWAIT 4")

[
object,
uuid(56a8689c-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMemAllocator : IUnknown
{
    HRESULT SetProperties(
        [in] ALLOCATOR_PROPERTIES* pRequest,
        [out] ALLOCATOR_PROPERTIES* pActual);

    HRESULT GetProperties(
        [out] ALLOCATOR_PROPERTIES* pProps);

    HRESULT Commit(void);

    HRESULT Decommit(void);

    HRESULT GetBuffer(
        [out] IMediaSample **ppBuffer,
        [in] REFERENCE_TIME * pStartTime,
        [in] REFERENCE_TIME * pEndTime,
        [in] DWORD dwFlags);

    HRESULT ReleaseBuffer(
        [in] IMediaSample *pBuffer);
}

typedef IMemAllocator *PMEMALLOCATOR;

[
object,
uuid(379a0cf0-c1de-11d2-abf5-00a0c905f375),
pointer_default(unique)
]
interface IMemAllocatorCallbackTemp : IMemAllocator
{
    HRESULT SetNotify(
        [in] IMemAllocatorNotifyCallbackTemp *pNotify);

    HRESULT GetFreeCount(
        [out] LONG *plBuffersFree);
}

[
object,
uuid(92980b30-c1de-11d2-abf5-00a0c905f375),
pointer_default(unique)
]
interface IMemAllocatorNotifyCallbackTemp : IUnknown
{
    HRESULT NotifyRelease();
}

[
object,
uuid(56a8689d-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMemInputPin : IUnknown
{
    HRESULT GetAllocator(
        [out] IMemAllocator ** ppAllocator);

    HRESULT NotifyAllocator(
        [in] IMemAllocator * pAllocator,
        [in] BOOL bReadOnly);

    HRESULT GetAllocatorRequirements( [out] ALLOCATOR_PROPERTIES*pProps );

    HRESULT Receive(
        [in] IMediaSample * pSample);

    HRESULT ReceiveMultiple(
        [in, size_is(nSamples)] IMediaSample **pSamples,
        [in] long nSamples,
        [out] long *nSamplesProcessed);

    HRESULT ReceiveCanBlock();
}

typedef IMemInputPin *PMEMINPUTPIN;

[
object,
uuid(a3d8cec0-7e5a-11cf-bbc5-00805f6cef20),
pointer_default(unique)
]
interface IAMovieSetup : IUnknown
{
    HRESULT Register( );
    HRESULT Unregister( );
}

typedef IAMovieSetup *PAMOVIESETUP;

typedef enum AM_SEEKING_SeekingFlags
{
    AM_SEEKING_NoPositioning            = 0x00,
    AM_SEEKING_AbsolutePositioning      = 0x01,
    AM_SEEKING_RelativePositioning      = 0x02,
    AM_SEEKING_IncrementalPositioning   = 0x03,
    AM_SEEKING_PositioningBitsMask      = 0x03,
    AM_SEEKING_SeekToKeyFrame           = 0x04,
    AM_SEEKING_ReturnTime               = 0x08,
    AM_SEEKING_Segment                  = 0x10,
    AM_SEEKING_NoFlush                  = 0x20
} AM_SEEKING_SEEKING_FLAGS;

typedef enum AM_SEEKING_SeekingCapabilities
{
    AM_SEEKING_CanSeekAbsolute     = 0x001,
    AM_SEEKING_CanSeekForwards     = 0x002,
    AM_SEEKING_CanSeekBackwards    = 0x004,
    AM_SEEKING_CanGetCurrentPos    = 0x008,
    AM_SEEKING_CanGetStopPos       = 0x010,
    AM_SEEKING_CanGetDuration      = 0x020,
    AM_SEEKING_CanPlayBackwards    = 0x040,
    AM_SEEKING_CanDoSegments       = 0x080,
    AM_SEEKING_Source              = 0x100
} AM_SEEKING_SEEKING_CAPABILITIES;

[
object,
uuid(36b73880-c2c8-11cf-8b46-00805f6cef60),
pointer_default(unique)
]
interface IMediaSeeking : IUnknown
{
    HRESULT GetCapabilities( [out] DWORD * pCapabilities );

    HRESULT CheckCapabilities( [in,out] DWORD * pCapabilities );

    HRESULT IsFormatSupported([in] const GUID * pFormat);

    HRESULT QueryPreferredFormat([out] GUID * pFormat);

    HRESULT GetTimeFormat([out] GUID *pFormat);

    HRESULT IsUsingTimeFormat([in] const GUID * pFormat);

    HRESULT SetTimeFormat([in] const GUID * pFormat);

    HRESULT GetDuration([out] LONGLONG *pDuration);

    HRESULT GetStopPosition([out] LONGLONG *pStop);

    HRESULT GetCurrentPosition([out] LONGLONG *pCurrent);

    HRESULT ConvertTimeFormat([out] LONGLONG * pTarget, [in] const GUID * pTargetFormat,
                              [in]  LONGLONG    Source, [in] const GUID * pSourceFormat );

    HRESULT SetPositions(
        [in,out] LONGLONG * pCurrent,
        [in] DWORD dwCurrentFlags,
        [in,out] LONGLONG * pStop,
        [in] DWORD dwStopFlags);

    HRESULT GetPositions(
        [out] LONGLONG * pCurrent,
        [out] LONGLONG * pStop);

    HRESULT GetAvailable(
        [out] LONGLONG * pEarliest,
        [out] LONGLONG * pLatest);

    HRESULT SetRate([in]  double dRate);

    HRESULT GetRate([out] double * pdRate);

    HRESULT GetPreroll([out] LONGLONG * pllPreroll);
}

typedef IMediaSeeking *PMEDIASEEKING;

enum tagAM_MEDIAEVENT_FLAGS
{
    AM_MEDIAEVENT_NONOTIFY = 0x01
};
