/*****************************************************************************
 * dtv_bda.hpp : DirectShow BDA graph builder header for Mpxplay-MMC
 *****************************************************************************
 *
 * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
 *         Attila Padar <mpxplay(at)freemail(dot)com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * ( at your option ) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

using namespace std;

#include <wtypes.h>
#include <unknwn.h>
#include <ole2.h>
#include <limits.h>

/* FIXME: mingw.org doesn't define secure versions of
 * http://msdn.microsoft.com/en-us/library/f30dzcf6.aspxu */
#define NO_DSHOW_STRSAFE
#include <dshow.h>

#include <comcat.h>
#include <tuner.h>
#include <qedit.h>

#include "newfunc/newfunc.h"
#include "dtv_drv.h"

class BDAGraph : public ISampleGrabberCB
{
public:
    BDAGraph();
    virtual ~BDAGraph();
    int BufferAdd(dvb_device_t *d);
    int BufferRemove(dvb_device_t *d);
    void BuffersAllReadUnlock(void);
    void BuffersAllReset(void);
    void BuffersAllClose(void);
    int  BuffersAllRefill(dvb_device_t *d);
    int  BufferRead(dvb_device_t *d, uint8_t *destbuf, int requested_bytes);

    int SubmitTuneRequest(dvb_device_t *d);
    int SetInversion(dvb_device_t *d, int);
    int GetSignalStrength(void);

    int InitATSCtuner(dvb_device_t *d);
    int InitCQAMtuner(dvb_device_t *d);
    int InitDVBCtuner(dvb_device_t *d);
    int InitDVBTtuner(dvb_device_t *d);
    int InitDVBStuner(dvb_device_t *d);

    HRESULT StopFilter();
    void ClearFilter();
    dtvbda_data_buffer_s *data_buffers_chain; /* buffer chain for the connected clients */

private:
    ULONG ul_cbrc;
    STDMETHODIMP_( ULONG ) AddRef(void) { return ++ul_cbrc; }
    STDMETHODIMP_( ULONG ) Release(void) { return --ul_cbrc; }
    STDMETHODIMP QueryInterface(REFIID /*riid*/, void** /*p_p_object*/ ) { return E_NOTIMPL; }
    STDMETHODIMP SampleCB(double d_time, IMediaSample *p_sample);
    STDMETHODIMP BufferCB(double d_time, BYTE* p_buffer, long l_buffer_len);

    CLSID     guid_network_type;       /* network type in use */
    long      l_tuner_used;            /* Index of the Tuning Device in use */
    int       samplecb_counter;        /* counter to detect initial errors */
    WINBOOL   is_discontinuity;        /* stream error */
    IRunningObjectTable *p_ro_table;
    IMoniker  *p_moniker;
    DWORD     d_graph_register;        /* registration number for the RunningObjectTable */
    void     *data_bufferchain_mutex;  /* mutex for buffer chain */
    dtvbda_data_buffer_s data_buffer_device_read; /* buffer to read from device */
    mpxp_int64_t timeout_at_read;

    IMediaControl*    media_control_handler;
    IGraphBuilder*    filter_graph_handler;
    ITuningSpace*     tuning_space_handler;
    ITuneRequest*     tune_request_handler;
    IDVBTuneRequest*  dvb_tunerequest_handler;

    IDVBTLocator*     dvbt_locator_handler;

    ICreateDevEnum* p_system_dev_enum;
    IBaseFilter*    p_network_provider;
    IBaseFilter*    p_tuner_device;
    IBaseFilter*    p_capture_device;
    IBaseFilter*    p_sample_grabber;
    IBaseFilter*    p_mpeg_demux;
    IBaseFilter*    p_transport_info;
    IScanningTuner* p_scanning_tuner;
    ISampleGrabber* p_grabber;

    HRESULT SetUpTuner(dvb_device_t *d, REFCLSID guid_this_network_type );
    HRESULT Build(dvb_device_t *d);
    HRESULT Check(dvb_device_t *d, REFCLSID guid_this_network_type );
    HRESULT GetFilterName(IBaseFilter *p_filter, char **psz_bstr_name );
    HRESULT GetPinName(IPin* p_pin, char **psz_bstr_name );
    HRESULT FindFilter(REFCLSID clsid, long *i_moniker_used, IBaseFilter *p_upstream, IBaseFilter **p_p_downstream);
    HRESULT ConnectFilterPins(IBaseFilter *p_filter_upstream, IBaseFilter *p_filter_downstream);
    HRESULT StartFilter();
    HRESULT DestroyFilter();
    HRESULT RegisterFilter();
    void    DeregisterFilter();
};
