Commit e236a562 authored by Ken Self's avatar Ken Self Committed by Rémi Denis-Courmont

BDA allow card selection

Signed-off-by: default avatarRémi Denis-Courmont <rdenis@simphalempin.com>
parent cac27358
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
***************************************************************************** *****************************************************************************
* Copyright (C) 2007 the VideoLAN team * Copyright (C) 2007 the VideoLAN team
* *
* Author: Ken Self <kens@campoz.fslife.co.uk> * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -191,19 +191,20 @@ vlc_module_begin () ...@@ -191,19 +191,20 @@ vlc_module_begin ()
add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, add_integer( "dvb-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
CACHING_LONGTEXT, true ); CACHING_LONGTEXT, true );
add_integer( "dvb-frequency", 11954000, NULL, FREQ_TEXT, FREQ_LONGTEXT, add_integer( "dvb-frequency", 0, NULL, FREQ_TEXT, FREQ_LONGTEXT,
false ); false );
# if defined(WIN32) || defined(WINCE) # if defined(WIN32) || defined(WINCE)
add_string( "dvb-network-name", NULL, NULL, NAME_TEXT, NAME_LONGTEXT, add_string( "dvb-network-name", NULL, NULL, NAME_TEXT, NAME_LONGTEXT,
true ); true );
add_string( "dvb-create-name", NULL, NULL, CREATE_TEXT, add_string( "dvb-create-name", NULL, NULL, CREATE_TEXT,
CREATE_LONGTEXT, true ); CREATE_LONGTEXT, true );
add_integer( "dvb-adapter", -1, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT,
true );
# else # else
add_integer( "dvb-adapter", 0, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT, /* dvb-device refers to a frontend within an adapter */
false );
add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT, add_integer( "dvb-device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT,
true ); true );
add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, true ) add_bool( "dvb-probe", 1, NULL, PROBE_TEXT, PROBE_LONGTEXT, true );
add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT, add_bool( "dvb-budget-mode", 0, NULL, BUDGET_TEXT, BUDGET_LONGTEXT,
true ); true );
# endif # endif
...@@ -227,6 +228,8 @@ vlc_module_begin () ...@@ -227,6 +228,8 @@ vlc_module_begin ()
LONGITUDE_LONGTEXT, true ); LONGITUDE_LONGTEXT, true );
add_string( "dvb-range", NULL, NULL, RANGE_TEXT, add_string( "dvb-range", NULL, NULL, RANGE_TEXT,
RANGE_LONGTEXT, true ); RANGE_LONGTEXT, true );
/* dvb-range corresponds to the BDA InputRange parameter which is
* used by some drivers to control the diseqc */
# else # else
add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT, add_integer( "dvb-satno", 0, NULL, SATNO_TEXT, SATNO_LONGTEXT,
true ); true );
...@@ -311,13 +314,14 @@ static int Open( vlc_object_t *p_this ) ...@@ -311,13 +314,14 @@ static int Open( vlc_object_t *p_this )
access_t *p_access = (access_t*)p_this; access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys; access_sys_t *p_sys;
const char* psz_module = "dvb"; const char* psz_module = "dvb";
const int i_param_count = 25; const int i_param_count = 26;
const char* psz_param[] = { "frequency", "bandwidth", const char* psz_param[] = { "frequency", "bandwidth",
"srate", "azimuth", "elevation", "longitude", "polarisation", "srate", "azimuth", "elevation", "longitude", "polarisation",
"modulation", "caching", "lnb-lof1", "lnb-lof2", "lnb-slof", "modulation", "caching", "lnb-lof1", "lnb-lof2", "lnb-slof",
"inversion", "network-id", "code-rate-hp", "code-rate-lp", "inversion", "network-id", "code-rate-hp", "code-rate-lp",
"guard", "transmission", "hierarchy", "range", "network-name", "guard", "transmission", "hierarchy", "range", "network-name",
"create-name", "major-channel", "minor-channel", "physical-channel" }; "create-name", "major-channel", "minor-channel", "physical-channel",
"adapter" };
const int i_type[] = { VLC_VAR_INTEGER, VLC_VAR_INTEGER, const int i_type[] = { VLC_VAR_INTEGER, VLC_VAR_INTEGER,
VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
...@@ -325,7 +329,7 @@ static int Open( vlc_object_t *p_this ) ...@@ -325,7 +329,7 @@ static int Open( vlc_object_t *p_this )
VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER,
VLC_VAR_INTEGER, VLC_VAR_STRING, VLC_VAR_STRING, VLC_VAR_STRING, VLC_VAR_INTEGER, VLC_VAR_STRING, VLC_VAR_STRING, VLC_VAR_STRING,
VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER }; VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER, VLC_VAR_INTEGER };
char psz_full_name[128]; char psz_full_name[128];
int i_ret; int i_ret;
...@@ -437,7 +441,7 @@ static int ParsePath( access_t *p_access, const char* psz_module, ...@@ -437,7 +441,7 @@ static int ParsePath( access_t *p_access, const char* psz_module,
i_token_len = strcspn( psz_parser, ":" ); i_token_len = strcspn( psz_parser, ":" );
if( i_token_len <= 0 ) if( i_token_len <= 0 )
i_token_len = strcspn( ++psz_parser, ":" ); i_token_len = strcspn( ++psz_parser, ":" );
do do
{ {
psz_token = strndup( psz_parser, i_token_len ); psz_token = strndup( psz_parser, i_token_len );
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
***************************************************************************** *****************************************************************************
* Copyright (C) 2007 the VideoLAN team * Copyright (C) 2007 the VideoLAN team
* *
* Author: Ken Self <kens@campoz.fslife.co.uk> * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -22,6 +22,10 @@ ...@@ -22,6 +22,10 @@
class IATSCChannelTuneRequest; class IATSCChannelTuneRequest;
class IATSCLocator; class IATSCLocator;
class IBDA_DeviceControl;
class IBDA_FrequencyFilter;
class IBDA_SignalStatistics;
class IBDA_Topology;
class IChannelTuneRequest; class IChannelTuneRequest;
class IComponent; class IComponent;
class IComponents; class IComponents;
...@@ -46,6 +50,14 @@ class ITuneRequest; ...@@ -46,6 +50,14 @@ class ITuneRequest;
class ITuningSpace; class ITuningSpace;
class ITuningSpaceContainer; class ITuningSpaceContainer;
class ITuningSpaces; class ITuningSpaces;
class IMpeg2Data;
class IGuideData;
class IGuideDataEvent;
class ISectionList;
class IEnumTuneRequests;
class IEnumGuideDataProperties;
class IGuideDataProperty;
class IMpeg2Stream;
typedef enum BinaryConvolutionCodeRate typedef enum BinaryConvolutionCodeRate
{ {
...@@ -179,6 +191,27 @@ typedef enum TransmissionMode ...@@ -179,6 +191,27 @@ typedef enum TransmissionMode
BDA_XMIT_MODE_MAX, BDA_XMIT_MODE_MAX,
} TransmissionMode; } TransmissionMode;
typedef struct _BDANODE_DESCRIPTOR
{
ULONG ulBdaNodeType;
GUID guidFunction;
GUID guidName;
} BDANODE_DESCRIPTOR, *PBDANODE_DESCRIPTOR;
typedef struct _BDA_TEMPLATE_CONNECTION
{
ULONG FromNodeType;
ULONG FromNodePinType;
ULONG ToNodeType;
ULONG ToNodePinType;
} BDA_TEMPLATE_CONNECTION, *PBDA_TEMPLATE_CONNECTION;
typedef struct _BDA_TEMPLATE_PIN_JOINT
{
ULONG uliTemplateConnection;
ULONG ulcInstancesMax;
} BDA_TEMPLATE_PIN_JOINT, *PBDA_TEMPLATE_PIN_JOINT;
class IComponent : public IDispatch class IComponent : public IDispatch
{ {
public: public:
...@@ -284,7 +317,8 @@ public: ...@@ -284,7 +317,8 @@ public:
virtual HRESULT __stdcall get_TuningSpace( virtual HRESULT __stdcall get_TuningSpace(
ITuningSpace** p_p_tuning_space )=0; ITuningSpace** p_p_tuning_space )=0;
virtual HRESULT __stdcall put_TuningSpace( ITuningSpace* p_tuning_space )=0; virtual HRESULT __stdcall put_TuningSpace( ITuningSpace* p_tuning_space )=0;
virtual HRESULT __stdcall EnumTuningSpaces( IEnumTuningSpaces** p_p_enum )=0; virtual HRESULT __stdcall EnumTuningSpaces(
IEnumTuningSpaces** p_p_enum )=0;
virtual HRESULT __stdcall get_TuneRequest( virtual HRESULT __stdcall get_TuneRequest(
ITuneRequest** p_p_tune_request )=0; ITuneRequest** p_p_tune_request )=0;
virtual HRESULT __stdcall put_TuneRequest( ITuneRequest* p_tune_request )=0; virtual HRESULT __stdcall put_TuneRequest( ITuneRequest* p_tune_request )=0;
...@@ -541,6 +575,344 @@ public: ...@@ -541,6 +575,344 @@ public:
IEnumTuningSpaces** p_p_enum )=0; IEnumTuningSpaces** p_p_enum )=0;
}; };
class IBDA_DeviceControl : public IUnknown
{
public:
virtual HRESULT __stdcall StartChanges( void )=0;
virtual HRESULT __stdcall CheckChanges( void )=0;
virtual HRESULT __stdcall CommitChanges( void )=0;
virtual HRESULT __stdcall GetChangeState( ULONG *pState )=0;
};
class IBDA_FrequencyFilter : public IUnknown
{
public:
virtual HRESULT __stdcall put_Autotune( ULONG ulTransponder )=0;
virtual HRESULT __stdcall get_Autotune( ULONG *pulTransponder )=0;
virtual HRESULT __stdcall put_Frequency( ULONG ulFrequency )=0;
virtual HRESULT __stdcall get_Frequency( ULONG *pulFrequency )=0;
virtual HRESULT __stdcall put_Polarity( Polarisation Polarity )=0;
virtual HRESULT __stdcall get_Polarity( Polarisation *pPolarity )=0;
virtual HRESULT __stdcall put_Range( ULONG ulRange )=0;
virtual HRESULT __stdcall get_Range( ULONG *pulRange )=0;
virtual HRESULT __stdcall put_Bandwidth( ULONG ulBandwidth )=0;
virtual HRESULT __stdcall get_Bandwidth( ULONG *pulBandwidth )=0;
virtual HRESULT __stdcall put_FrequencyMultiplier( ULONG ulMultiplier )=0;
virtual HRESULT __stdcall get_FrequencyMultiplier(
ULONG *pulMultiplier )=0;
};
class IBDA_SignalStatistics : public IUnknown
{
public:
virtual HRESULT __stdcall put_SignalStrength( LONG lDbStrength )=0;
virtual HRESULT __stdcall get_SignalStrength( LONG *plDbStrength )=0;
virtual HRESULT __stdcall put_SignalQuality( LONG lPercentQuality )=0;
virtual HRESULT __stdcall get_SignalQuality( LONG *plPercentQuality )=0;
virtual HRESULT __stdcall put_SignalPresent( BOOLEAN fPresent )=0;
virtual HRESULT __stdcall get_SignalPresent( BOOLEAN *pfPresent )=0;
virtual HRESULT __stdcall put_SignalLocked( BOOLEAN fLocked )=0;
virtual HRESULT __stdcall get_SignalLocked( BOOLEAN *pfLocked )=0;
virtual HRESULT __stdcall put_SampleTime( LONG lmsSampleTime )=0;
virtual HRESULT __stdcall get_SampleTime( LONG *plmsSampleTime )=0;
};
class IBDA_Topology : public IUnknown
{
public:
virtual HRESULT __stdcall GetNodeTypes( ULONG *pulcNodeTypes,
ULONG ulcNodeTypesMax, ULONG rgulNodeTypes[] )=0;
virtual HRESULT __stdcall GetNodeDescriptors( ULONG *ulcNodeDescriptors,
ULONG ulcNodeDescriptorsMax,
BDANODE_DESCRIPTOR rgNodeDescriptors[] )=0;
virtual HRESULT __stdcall GetNodeInterfaces( ULONG ulNodeType,
ULONG *pulcInterfaces, ULONG ulcInterfacesMax,
GUID rgguidInterfaces[] )=0;
virtual HRESULT __stdcall GetPinTypes( ULONG *pulcPinTypes,
ULONG ulcPinTypesMax, ULONG rgulPinTypes[] )=0;
virtual HRESULT __stdcall GetTemplateConnections( ULONG *pulcConnections,
ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION rgConnections[] )=0;
virtual HRESULT __stdcall CreatePin( ULONG ulPinType, ULONG *pulPinId )=0;
virtual HRESULT __stdcall DeletePin( ULONG ulPinId )=0;
virtual HRESULT __stdcall SetMediaType( ULONG ulPinId,
AM_MEDIA_TYPE *pMediaType )=0;
virtual HRESULT __stdcall SetMedium( ULONG ulPinId,
REGPINMEDIUM *pMedium )=0;
virtual HRESULT __stdcall CreateTopology( ULONG ulInputPinId,
ULONG ulOutputPinId )=0;
virtual HRESULT __stdcall GetControlNode( ULONG ulInputPinId,
ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode )=0;
};
typedef struct _MPEG_HEADER_BITS_MIDL
{
WORD Bits;
} MPEG_HEADER_BITS_MIDL;
typedef struct _MPEG_HEADER_VERSION_BITS_MIDL
{
BYTE Bits;
} MPEG_HEADER_VERSION_BITS_MIDL;
typedef WORD PID;
typedef BYTE TID;
typedef struct _SECTION
{
TID TableId;
union
{
MPEG_HEADER_BITS_MIDL S;
WORD W;
} Header;
BYTE SectionData[ 1 ];
} SECTION, *PSECTION;
typedef struct _LONG_SECTION
{
TID TableId;
union
{
MPEG_HEADER_BITS_MIDL S;
WORD W;
} Header;
WORD TableIdExtension;
union
{
MPEG_HEADER_VERSION_BITS_MIDL S;
BYTE B;
} Version;
BYTE SectionNumber;
BYTE LastSectionNumber;
BYTE RemainingData[ 1 ];
} LONG_SECTION;
typedef struct _MPEG_BCS_DEMUX
{
DWORD AVMGraphId;
} MPEG_BCS_DEMUX;
typedef struct _MPEG_WINSOC
{
DWORD AVMGraphId;
} MPEG_WINSOCK;
typedef enum
{
MPEG_CONTEXT_BCS_DEMUX = 0,
MPEG_CONTEXT_WINSOCK = MPEG_CONTEXT_BCS_DEMUX + 1
} MPEG_CONTEXT_TYPE;
typedef struct _MPEG_RQST_PACKET
{
DWORD dwLength;
PSECTION pSection;
} MPEG_RQST_PACKET, *PMPEG_RQST_PACKET;
typedef struct _MPEG_PACKET_LIST
{
WORD wPacketCount;
PMPEG_RQST_PACKET PacketList[ 1 ];
} MPEG_PACKET_LIST, *PMPEG_PACKET_LIST;
typedef struct _DSMCC_FILTER_OPTIONS
{
BOOL fSpecifyProtocol;
BYTE Protocol;
BOOL fSpecifyType;
BYTE Type;
BOOL fSpecifyMessageId;
WORD MessageId;
BOOL fSpecifyTransactionId;
BOOL fUseTrxIdMessageIdMask;
DWORD TransactionId;
BOOL fSpecifyModuleVersion;
BYTE ModuleVersion;
BOOL fSpecifyBlockNumber;
WORD BlockNumber;
BOOL fGetModuleCall;
WORD NumberOfBlocksInModule;
} DSMCC_FILTER_OPTIONS;
typedef struct _ATSC_FILTER_OPTIONS
{
BOOL fSpecifyEtmId;
DWORD EtmId;
} ATSC_FILTER_OPTIONS;
typedef struct _MPEG_STREAM_BUFFER
{
HRESULT hr;
DWORD dwDataBufferSize;
DWORD dwSizeOfDataRead;
BYTE *pDataBuffer;
} MPEG_STREAM_BUFFER, *PMPEG_STREAM_BUFFER;
typedef struct _MPEG_CONTEXT
{
MPEG_CONTEXT_TYPE Type;
union
{
MPEG_BCS_DEMUX Demux;
MPEG_WINSOCK Winsock;
} U;
} MPEG_CONTEXT, *PMPEG_CONTEXT;
typedef enum
{
MPEG_RQST_UNKNOWN = 0,
MPEG_RQST_GET_SECTION = MPEG_RQST_UNKNOWN + 1,
MPEG_RQST_GET_SECTION_ASYNC = MPEG_RQST_GET_SECTION + 1,
MPEG_RQST_GET_TABLE = MPEG_RQST_GET_SECTION_ASYNC + 1,
MPEG_RQST_GET_TABLE_ASYNC = MPEG_RQST_GET_TABLE + 1,
MPEG_RQST_GET_SECTIONS_STREAM = MPEG_RQST_GET_TABLE_ASYNC + 1,
MPEG_RQST_GET_PES_STREAM = MPEG_RQST_GET_SECTIONS_STREAM + 1,
MPEG_RQST_GET_TS_STREAM = MPEG_RQST_GET_PES_STREAM + 1,
MPEG_RQST_START_MPE_STREAM = MPEG_RQST_GET_TS_STREAM + 1
} MPEG_REQUEST_TYPE;
typedef struct _MPEG2_FILTER
{
BYTE bVersionNumber;
WORD wFilterSize;
BOOL fUseRawFilteringBits;
BYTE Filter[ 16 ];
BYTE Mask[ 16 ];
BOOL fSpecifyTableIdExtension;
WORD TableIdExtension;
BOOL fSpecifyVersion;
BYTE Version;
BOOL fSpecifySectionNumber;
BYTE SectionNumber;
BOOL fSpecifyCurrentNext;
BOOL fNext;
BOOL fSpecifyDsmccOptions;
DSMCC_FILTER_OPTIONS Dsmcc;
BOOL fSpecifyAtscOptions;
ATSC_FILTER_OPTIONS Atsc;
} MPEG2_FILTER, *PMPEG2_FILTER;
typedef struct _MPEG_HEADER_BITS
{
WORD SectionLength : 12;
WORD Reserved : 2;
WORD PrivateIndicator : 1;
WORD SectionSyntaxIndicator : 1;
} MPEG_HEADER_BITS, *PMPEG_HEADER_BITS;
typedef struct _MPEG_HEADER_VERSION_BITS
{
BYTE CurrentNextIndicator : 1;
BYTE VersionNumber : 5;
BYTE Reserved : 2;
} MPEG_HEADER_VERSION_BITS, *PMPEG_HEADER_VERSION_BITS;
class IMpeg2Data : public IUnknown
{
public:
virtual HRESULT __stdcall GetSection( PID pid, TID tid,
PMPEG2_FILTER pFilter, DWORD dwTimeout,
ISectionList **ppSectionList )=0;
virtual HRESULT __stdcall GetTable( PID pid, TID tid, PMPEG2_FILTER pFilter,
DWORD dwTimeout, ISectionList **ppSectionList )=0;
virtual HRESULT __stdcall GetStreamOfSections( PID pid, TID tid,
PMPEG2_FILTER pFilter, HANDLE hDataReadyEvent,
IMpeg2Stream **ppMpegStream )=0;
};
class IGuideData : public IUnknown
{
public:
virtual HRESULT __stdcall GetServices(
IEnumTuneRequests **ppEnumTuneRequestslass )=0;
virtual HRESULT __stdcall GetServiceProperties(
ITuneRequest *pTuneRequest,
IEnumGuideDataProperties **ppEnumProperties )=0;
virtual HRESULT __stdcall GetGuideProgramIDs(
IEnumVARIANT **pEnumPrograms )=0;
virtual HRESULT __stdcall GetProgramProperties(
VARIANT varProgramDescriptionID,
IEnumGuideDataProperties **ppEnumProperties )=0;
virtual HRESULT __stdcall GetScheduleEntryIDs(
IEnumVARIANT **pEnumScheduleEntries )=0;
virtual HRESULT __stdcall GetScheduleEntryProperties(
VARIANT varScheduleEntryDescriptionID,
IEnumGuideDataProperties **ppEnumProperties )=0;
};
class IGuideDataEvent : public IUnknown
{
public:
virtual HRESULT __stdcall GuideDataAcquired( void )=0;
virtual HRESULT __stdcall ProgramChanged(
VARIANT varProgramDescriptionID )=0;
virtual HRESULT __stdcall ServiceChanged(
VARIANT varServiceDescriptionID )=0;
virtual HRESULT __stdcall ScheduleEntryChanged(
VARIANT varScheduleEntryDescriptionID )=0;
virtual HRESULT __stdcall ProgramDeleted(
VARIANT varProgramDescriptionID )=0;
virtual HRESULT __stdcall ServiceDeleted(
VARIANT varServiceDescriptionID )=0;
virtual HRESULT __stdcall ScheduleDeleted(
VARIANT varScheduleEntryDescriptionID )=0;
};
class IGuideDataProperty : public IUnknown
{
public:
virtual HRESULT __stdcall get_Name( BSTR *pbstrName )=0;
virtual HRESULT __stdcall get_Language( long *idLang )=0;
virtual HRESULT __stdcall get_Value( VARIANT *pvar )=0;
};
class IMpeg2Stream : public IUnknown
{
public:
virtual HRESULT __stdcall Initialize( MPEG_REQUEST_TYPE requestType,
IMpeg2Data *pMpeg2Data, PMPEG_CONTEXT pContext, PID pid, TID tid,
PMPEG2_FILTER pFilter, HANDLE hDataReadyEvent )=0;
virtual HRESULT __stdcall SupplyDataBuffer(
PMPEG_STREAM_BUFFER pStreamBuffer )=0;
};
class ISectionList : public IUnknown
{
public:
virtual HRESULT __stdcall Initialize( MPEG_REQUEST_TYPE requestType,
IMpeg2Data *pMpeg2Data, PMPEG_CONTEXT pContext, PID pid, TID tid,
PMPEG2_FILTER pFilter, DWORD timeout, HANDLE hDoneEvent )=0;
virtual HRESULT __stdcall InitializeWithRawSections(
PMPEG_PACKET_LIST pmplSections )=0;
virtual HRESULT __stdcall CancelPendingRequest( void )=0;
virtual HRESULT __stdcall GetNumberOfSections( WORD *pCount )=0;
virtual HRESULT __stdcall GetSectionData( WORD sectionNumber,
DWORD *pdwRawPacketLength, PSECTION *ppSection )=0;
virtual HRESULT __stdcall GetProgramIdentifier( PID *pPid )=0;
virtual HRESULT __stdcall GetTableIdentifier( TID *pTableId )=0;
};
class IEnumGuideDataProperties : public IUnknown
{
public:
virtual HRESULT __stdcall Next( unsigned long celt,
IGuideDataProperty **ppprop, unsigned long *pcelt )=0;
virtual HRESULT __stdcall Skip( unsigned long celt )=0;
virtual HRESULT __stdcall Reset( void )=0;
virtual HRESULT __stdcall Clone( IEnumGuideDataProperties **ppenum )=0;
};
class IEnumTuneRequests : public IUnknown
{
public:
virtual HRESULT __stdcall Next( unsigned long celt, ITuneRequest **ppprop,
unsigned long *pcelt )=0;
virtual HRESULT __stdcall Skip( unsigned long celt )=0;
virtual HRESULT __stdcall Reset( void )=0;
virtual HRESULT __stdcall Clone( IEnumTuneRequests **ppenum )=0;
};
extern "C" { extern "C" {
extern const GUID CLSID_ATSCLocator; extern const GUID CLSID_ATSCLocator;
extern const GUID CLSID_ATSCNetworkProvider; extern const GUID CLSID_ATSCNetworkProvider;
...@@ -564,6 +936,13 @@ extern const GUID CLSID_SystemTuningSpaces; ...@@ -564,6 +936,13 @@ extern const GUID CLSID_SystemTuningSpaces;
extern const GUID IID_IATSCChannelTuneRequest; extern const GUID IID_IATSCChannelTuneRequest;
extern const GUID IID_IATSCLocator; extern const GUID IID_IATSCLocator;
extern const GUID IID_IBaseFilter; extern const GUID IID_IBaseFilter;
extern const GUID IID_IBDA_DeviceControl;
extern const GUID IID_IBDA_FrequencyFilter;
extern const GUID IID_IBDA_SignalStatistics;
/* Following symbol does not exist in library
extern const GUID IID_IBDA_Topology; */
const GUID IID_IBDA_Topology =
{0x79B56888,0x7FEA,0x4690,{0xB4,0x5D,0x38,0xFD,0x3C,0x78,0x49,0xBE}};
extern const GUID IID_ICreateDevEnum; extern const GUID IID_ICreateDevEnum;
extern const GUID IID_IDVBTLocator; extern const GUID IID_IDVBTLocator;
extern const GUID IID_IDVBCLocator; extern const GUID IID_IDVBCLocator;
...@@ -580,6 +959,17 @@ extern const GUID IID_IScanningTuner; ...@@ -580,6 +959,17 @@ extern const GUID IID_IScanningTuner;
extern const GUID IID_ITuner; extern const GUID IID_ITuner;
extern const GUID IID_ITuningSpace; extern const GUID IID_ITuningSpace;
extern const GUID IID_ITuningSpaceContainer; extern const GUID IID_ITuningSpaceContainer;
/* Following symbol does not exist in library
extern const GUID IID_IMpeg2Data; */
const GUID IID_IMpeg2Data =
{0x9B396D40,0xF380,0x4e3c,{0xA5,0x14,0x1A,0x82,0xBF,0x6E,0xBF,0xE6}};
extern const GUID IID_IGuideData;
extern const GUID IID_ISectionList;
extern const GUID IID_IEnumTuneRequests;
extern const GUID IID_IEnumGuideDataProperties;
extern const GUID IID_IGuideDataProperty;
extern const GUID IID_IMpeg2Stream;
extern const GUID IID_IGuideDataEvent;
extern const GUID MEDIATYPE_MPEG2_SECTIONS; extern const GUID MEDIATYPE_MPEG2_SECTIONS;
extern const GUID MEDIASUBTYPE_None; extern const GUID MEDIASUBTYPE_None;
...@@ -591,4 +981,7 @@ const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT = ...@@ -591,4 +981,7 @@ const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT =
{0xFD0A5AF4,0xB41D,0x11d2,{0x9c,0x95,0x00,0xc0,0x4f,0x79,0x71,0xe0}}; {0xFD0A5AF4,0xB41D,0x11d2,{0x9c,0x95,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
const GUID KSCATEGORY_BDA_NETWORK_TUNER = const GUID KSCATEGORY_BDA_NETWORK_TUNER =
{0x71985f48,0x1ca1,0x11d3,{0x9c,0xc8,0x00,0xc0,0x4f,0x79,0x71,0xe0}}; {0x71985f48,0x1ca1,0x11d3,{0x9c,0xc8,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
const GUID KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT =
{0xF4AEB342,0x0329,0x4fdd,{0xA8,0xFD,0x4A,0xFF,0x49,0x26,0xC9,0x78}};
}; };
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
***************************************************************************** *****************************************************************************
* Copyright( C ) 2007 the VideoLAN team * Copyright( C ) 2007 the VideoLAN team
* *
* Author: Ken Self <kens@campoz.fslife.co.uk> * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -781,10 +781,10 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -781,10 +781,10 @@ HRESULT BDAGraph::CreateTuneRequest()
bstr_name(NULL) {}; bstr_name(NULL) {};
~localComPtr() ~localComPtr()
{ {
if( p_tuning_space_container )
p_tuning_space_container->Release();
if( p_tuning_space_enum ) if( p_tuning_space_enum )
p_tuning_space_enum->Release(); p_tuning_space_enum->Release();
if( p_tuning_space_container )
p_tuning_space_container->Release();
if( p_this_tuning_space ) if( p_this_tuning_space )
p_this_tuning_space->Release(); p_this_tuning_space->Release();
SysFreeString( bstr_name ); SysFreeString( bstr_name );
...@@ -840,15 +840,20 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -840,15 +840,20 @@ HRESULT BDAGraph::CreateTuneRequest()
} }
} }
/* else */ /* else */
p_tuning_space->Release(); if( p_tuning_space )
p_tuning_space->Release();
if( p_tune_request )
p_tune_request->Release();
p_tuning_space = NULL; p_tuning_space = NULL;
p_tune_request = NULL;
} }
/* Force use of the first available Tuner Device during Build */ /* Force use of the first available Tuner Device during Build */
l_tuner_used = -1; l_tuner_used = -1;
/* Get the SystemTuningSpaces container to enumerate through all the /* Get the SystemTuningSpaces container to enumerate through all the
* defined tuning spaces */ * defined tuning spaces.
* l.p_tuning_space_container->Refcount = 1 */
hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC, hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container ); IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -858,6 +863,10 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -858,6 +863,10 @@ HRESULT BDAGraph::CreateTuneRequest()
return hr; return hr;
} }
/* Get the SystemTuningSpaces container to enumerate through all the
* defined tuning spaces.
* l.p_tuning_space_container->Refcount = 2
* l.p_tuning_space_enum->Refcount = 1 */
hr = l.p_tuning_space_container->get_EnumTuningSpaces( hr = l.p_tuning_space_container->get_EnumTuningSpaces(
&l.p_tuning_space_enum ); &l.p_tuning_space_enum );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -867,9 +876,17 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -867,9 +876,17 @@ HRESULT BDAGraph::CreateTuneRequest()
return hr; return hr;
} }
while( l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL ) == do
S_OK )
{ {
/* l.p_this_tuning_space->RefCount = 1 after the first pass
* Release before overwriting with Next */
if( l.p_this_tuning_space )
l.p_this_tuning_space->Release();
l.p_this_tuning_space = NULL;
hr = l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL );
if( hr != S_OK ) break;
hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type ); hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
/* GUID_NULL means a non-BDA network was found e.g analog /* GUID_NULL means a non-BDA network was found e.g analog
...@@ -878,6 +895,8 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -878,6 +895,8 @@ HRESULT BDAGraph::CreateTuneRequest()
if( guid_this_network_type == guid_network_type ) if( guid_this_network_type == guid_network_type )
{ {
/* QueryInterface to clone l.p_this_tuning_space
* l.p_this_tuning_space->RefCount = 2 */
hr = l.p_this_tuning_space->QueryInterface( IID_ITuningSpace, hr = l.p_this_tuning_space->QueryInterface( IID_ITuningSpace,
(void**)&p_tuning_space ); (void**)&p_tuning_space );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -901,15 +920,22 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -901,15 +920,22 @@ HRESULT BDAGraph::CreateTuneRequest()
{ {
msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S", msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
l.bstr_name ); l.bstr_name );
/* CreateTuneRequest adds TuneRequest to p_tuning_space
* p_tune_request->RefCount = 1 */
hr = p_tuning_space->CreateTuneRequest( &p_tune_request ); hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
if( FAILED( hr ) ) if( FAILED( hr ) )
msg_Warn( p_access, "CreateTuneRequest: "\ msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot Create Tune Request: hr=0x%8lx", hr ); "Cannot Create Tune Request: hr=0x%8lx", hr );
return hr; return hr;
} }
if( p_tuning_space )
p_tuning_space->Release();
p_tuning_space = NULL;
} }
} }
/* No tune request was found. If the create-name parameter was set then while( true );
/* No tuning space was found. If the create-name parameter was set then
* create a tuning space. By rights should use the same name used in * create a tuning space. By rights should use the same name used in
* network-name * network-name
* Also would be nice to copy a tuning space but we only come here if we do * Also would be nice to copy a tuning space but we only come here if we do
...@@ -951,8 +977,10 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -951,8 +977,10 @@ HRESULT BDAGraph::CreateTuneRequest()
msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %S", msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %S",
l.bstr_name ); l.bstr_name );
} }
hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC, hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC,
IID_ITuningSpace, (void**)&p_tuning_space ); IID_ITuningSpace, (void**)&p_tuning_space );
if( FAILED( hr ) ) if( FAILED( hr ) )
msg_Warn( p_access, "CreateTuneRequest: "\ msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot CoCreate new TuningSpace: hr=0x%8lx", hr ); "Cannot CoCreate new TuningSpace: hr=0x%8lx", hr );
...@@ -971,18 +999,24 @@ HRESULT BDAGraph::CreateTuneRequest() ...@@ -971,18 +999,24 @@ HRESULT BDAGraph::CreateTuneRequest()
if( FAILED( hr ) ) if( FAILED( hr ) )
msg_Warn( p_access, "CreateTuneRequest: "\ msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot Put Friendly Name: hr=0x%8lx", hr ); "Cannot Put Friendly Name: hr=0x%8lx", hr );
if( SUCCEEDED( hr ) ) if( SUCCEEDED( hr ) )
hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id ); hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
msg_Warn( p_access, "CreateTuneRequest: "\ msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot Create new TuningSpace: hr=0x%8lx", hr ); "Cannot Create new TuningSpace: hr=0x%8lx", hr );
return hr; return hr;
} }
msg_Dbg( p_access, "CreateTuneRequest: Tuning Space: %S created",
l.bstr_name );
hr = p_tuning_space->CreateTuneRequest( &p_tune_request ); hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
if( FAILED( hr ) ) if( FAILED( hr ) )
msg_Warn( p_access, "CreateTuneRequest: "\ msg_Warn( p_access, "CreateTuneRequest: "\
"Cannot Create Tune Request: hr=0x%8lx", hr ); "Cannot Create Tune Request: hr=0x%8lx", hr );
return hr; return hr;
} }
...@@ -1094,7 +1128,18 @@ HRESULT BDAGraph::Build() ...@@ -1094,7 +1128,18 @@ HRESULT BDAGraph::Build()
} }
/* Add the Network Tuner to the Network Provider. On subsequent calls, /* Add the Network Tuner to the Network Provider. On subsequent calls,
* l_tuner_used will cause a different tuner to be selected */ * l_tuner_used will cause a different tuner to be selected
* To select a specific device first get the parameter that nominates the
* device (dvb-adapter) and use the value to initialise l_tuner_used.
* When FindFilter returns check the contents of l_tuner_used.
* If it is not what was selected then the requested device was not
* available so return with an error. */
long l_adapter = -1;
l_adapter = var_GetInteger( p_access, "dvb-adapter" );
if( l_tuner_used < 0 && l_adapter >= 0 )
l_tuner_used = l_adapter - 1;
hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used, hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used,
p_network_provider, &p_tuner_device ); p_network_provider, &p_tuner_device );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1104,6 +1149,13 @@ HRESULT BDAGraph::Build() ...@@ -1104,6 +1149,13 @@ HRESULT BDAGraph::Build()
"hr=0x%8lx", hr ); "hr=0x%8lx", hr );
return hr; return hr;
} }
if( l_adapter > 0 && l_tuner_used != l_adapter )
{
msg_Warn( p_access, "Build: "\
"Tuner device %d is not available", l_adapter );
return E_FAIL;
}
msg_Dbg( p_access, "BDAGraph: Using adapter %d", l_tuner_used );
/* Always look for all capture devices to match the Network Tuner */ /* Always look for all capture devices to match the Network Tuner */
l_capture_used = -1; l_capture_used = -1;
...@@ -1119,6 +1171,9 @@ HRESULT BDAGraph::Build() ...@@ -1119,6 +1171,9 @@ HRESULT BDAGraph::Build()
"Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr ); "Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr );
} }
if( p_sample_grabber )
p_sample_grabber->Release();
p_sample_grabber = NULL;
/* Insert the Sample Grabber to tap into the Transport Stream. */ /* Insert the Sample Grabber to tap into the Transport Stream. */
hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&p_sample_grabber ); IID_IBaseFilter, (void**)&p_sample_grabber );
...@@ -1136,6 +1191,9 @@ HRESULT BDAGraph::Build() ...@@ -1136,6 +1191,9 @@ HRESULT BDAGraph::Build()
return hr; return hr;
} }
if( p_grabber )
p_grabber->Release();
p_grabber = NULL;
hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber, hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber,
(void**)&p_grabber ); (void**)&p_grabber );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1155,6 +1213,7 @@ HRESULT BDAGraph::Build() ...@@ -1155,6 +1213,7 @@ HRESULT BDAGraph::Build()
"Cannot set media type on grabber filter: hr=0x%8lx", hr ); "Cannot set media type on grabber filter: hr=0x%8lx", hr );
return hr; return hr;
} }
hr = Connect( p_capture_device, p_sample_grabber ); hr = Connect( p_capture_device, p_sample_grabber );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
...@@ -1232,6 +1291,9 @@ HRESULT BDAGraph::Build() ...@@ -1232,6 +1291,9 @@ HRESULT BDAGraph::Build()
} }
/* The Media Control is used to Run and Stop the Graph */ /* The Media Control is used to Run and Stop the Graph */
if( p_media_control )
p_media_control->Release();
p_media_control = NULL;
hr = p_filter_graph->QueryInterface( IID_IMediaControl, hr = p_filter_graph->QueryInterface( IID_IMediaControl,
(void**)&p_media_control ); (void**)&p_media_control );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1273,14 +1335,14 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, ...@@ -1273,14 +1335,14 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
{ ::VariantInit(&var_bstr); }; { ::VariantInit(&var_bstr); };
~localComPtr() ~localComPtr()
{ {
if( p_property_bag )
p_property_bag->Release();
if( p_filter )
p_filter->Release();
if( p_moniker ) if( p_moniker )
p_moniker->Release(); p_moniker->Release();
if( p_moniker_enum ) if( p_moniker_enum )
p_moniker_enum->Release(); p_moniker_enum->Release();
if( p_filter )
p_filter->Release();
if( p_property_bag )
p_property_bag->Release();
::VariantClear(&var_bstr); ::VariantClear(&var_bstr);
} }
} l; } l;
...@@ -1305,27 +1367,38 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, ...@@ -1305,27 +1367,38 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
"Cannot CreateClassEnumerator: hr=0x%8lx", hr ); "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
return E_FAIL; return E_FAIL;
} }
while( l.p_moniker_enum->Next( 1, &l.p_moniker, 0 ) == S_OK )
do
{ {
/* We are overwriting l.p_moniker so we should Release and nullify
* It is important that p_moniker and p_property_bag are fully released
* l.p_filter may not be dereferenced so we could force to NULL */
if( l.p_property_bag )
l.p_property_bag->Release();
l.p_property_bag = NULL;
if( l.p_filter )
l.p_filter->Release();
l.p_filter = NULL;
if( l.p_moniker )
l.p_moniker->Release();
l.p_moniker = NULL;
hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
if( hr != S_OK ) break;
i_moniker_index++; i_moniker_index++;
/* Skip over devices already found on previous calls */ /* Skip over devices already found on previous calls */
if( i_moniker_index <= *i_moniker_used ) continue; if( i_moniker_index <= *i_moniker_used ) continue;
*i_moniker_used = i_moniker_index; *i_moniker_used = i_moniker_index;
/* l.p_filter is Released at the top of the loop */
hr = l.p_moniker->BindToObject( NULL, NULL, IID_IBaseFilter, hr = l.p_moniker->BindToObject( NULL, NULL, IID_IBaseFilter,
(void**)&l.p_filter ); (void**)&l.p_filter );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
if( l.p_moniker )
l.p_moniker->Release();
l.p_moniker = NULL;
if( l.p_filter)
l.p_filter->Release();
l.p_filter = NULL;
continue; continue;
} }
/* l.p_property_bag is released at the top of the loop */
hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag, hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
(void**)&l.p_property_bag ); (void**)&l.p_property_bag );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1334,7 +1407,6 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, ...@@ -1334,7 +1407,6 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
"Cannot Bind to Property Bag: hr=0x%8lx", hr ); "Cannot Bind to Property Bag: hr=0x%8lx", hr );
return hr; return hr;
} }
hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL ); hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
...@@ -1354,6 +1426,7 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, ...@@ -1354,6 +1426,7 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
hr = Connect( p_upstream, l.p_filter ); hr = Connect( p_upstream, l.p_filter );
if( SUCCEEDED( hr ) ) if( SUCCEEDED( hr ) )
{ {
/* p_p_downstream has not been touched yet so no release needed */
msg_Dbg( p_access, "FindFilter: Connected %S", l.var_bstr.bstrVal ); msg_Dbg( p_access, "FindFilter: Connected %S", l.var_bstr.bstrVal );
l.p_filter->QueryInterface( IID_IBaseFilter, l.p_filter->QueryInterface( IID_IBaseFilter,
(void**)p_p_downstream ); (void**)p_p_downstream );
...@@ -1368,13 +1441,8 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used, ...@@ -1368,13 +1441,8 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
return hr; return hr;
} }
if( l.p_moniker )
l.p_moniker->Release();
l.p_moniker = NULL;
if( l.p_filter)
l.p_filter->Release();
l.p_filter = NULL;
} }
while( true );
hr = E_FAIL; hr = E_FAIL;
msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr ); msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr );
...@@ -1400,21 +1468,20 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream ) ...@@ -1400,21 +1468,20 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
p_pin_temp(NULL) { }; p_pin_temp(NULL) { };
~localComPtr() ~localComPtr()
{ {
if( p_pin_upstream ) if( p_pin_temp )
p_pin_upstream->Release(); p_pin_temp->Release();
if( p_pin_downstream ) if( p_pin_downstream )
p_pin_downstream->Release(); p_pin_downstream->Release();
if( p_pin_upstream_enum ) if( p_pin_upstream )
p_pin_upstream_enum->Release(); p_pin_upstream->Release();
if( p_pin_downstream_enum ) if( p_pin_downstream_enum )
p_pin_downstream_enum->Release(); p_pin_downstream_enum->Release();
if( p_pin_temp ) if( p_pin_upstream_enum )
p_pin_temp->Release(); p_pin_upstream_enum->Release();
} }
} l; } l;
PIN_INFO pin_info_upstream; PIN_DIRECTION pin_dir;
PIN_INFO pin_info_downstream;
hr = p_upstream->EnumPins( &l.p_pin_upstream_enum ); hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1423,26 +1490,36 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream ) ...@@ -1423,26 +1490,36 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
"Cannot get upstream filter enumerator: hr=0x%8lx", hr ); "Cannot get upstream filter enumerator: hr=0x%8lx", hr );
return hr; return hr;
} }
while( l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 ) == S_OK )
do
{ {
hr = l.p_pin_upstream->QueryPinInfo( &pin_info_upstream ); /* Release l.p_pin_upstream before next iteration */
if( l.p_pin_upstream )
l.p_pin_upstream ->Release();
l.p_pin_upstream = NULL;
hr = l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 );
if( hr != S_OK ) break;
hr = l.p_pin_upstream->QueryDirection( &pin_dir );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
msg_Warn( p_access, "Connect: "\ msg_Warn( p_access, "Connect: "\
"Cannot get upstream filter pin information: hr=0x%8lx", hr ); "Cannot get upstream filter pin direction: hr=0x%8lx", hr );
return hr; return hr;
} }
hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream ); hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
if( hr == S_OK ) if( SUCCEEDED( hr ) )
{
l.p_pin_downstream->Release(); l.p_pin_downstream->Release();
if(FAILED( hr ) && hr != VFW_E_NOT_CONNECTED ) l.p_pin_downstream = NULL;
}
if( FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
{ {
msg_Warn( p_access, "Connect: "\ msg_Warn( p_access, "Connect: "\
"Cannot check upstream filter connection: hr=0x%8lx", hr ); "Cannot check upstream filter connection: hr=0x%8lx", hr );
return hr; return hr;
} }
if(( pin_info_upstream.dir == PINDIR_OUTPUT ) && if( ( pin_dir == PINDIR_OUTPUT ) && ( hr == VFW_E_NOT_CONNECTED ) )
( hr == VFW_E_NOT_CONNECTED ) )
{ {
/* The upstream pin is not yet connected so check each pin on the /* The upstream pin is not yet connected so check each pin on the
* downstream filter */ * downstream filter */
...@@ -1453,19 +1530,33 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream ) ...@@ -1453,19 +1530,33 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
"downstream filter enumerator: hr=0x%8lx", hr ); "downstream filter enumerator: hr=0x%8lx", hr );
return hr; return hr;
} }
while( l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 ) do
== S_OK )
{ {
hr = l.p_pin_downstream->QueryPinInfo( &pin_info_downstream ); /* Release l.p_pin_downstream before next iteration */
if( l.p_pin_downstream )
l.p_pin_downstream ->Release();
l.p_pin_downstream = NULL;
hr = l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 );
if( hr != S_OK ) break;
hr = l.p_pin_downstream->QueryDirection( &pin_dir );
if( FAILED( hr ) ) if( FAILED( hr ) )
{ {
msg_Warn( p_access, "Connect: Cannot get "\ msg_Warn( p_access, "Connect: Cannot get "\
"downstream filter pin information: hr=0x%8lx", hr ); "downstream filter pin direction: hr=0x%8lx", hr );
return hr; return hr;
} }
/* Looking for a free Pin to connect to
* A connected Pin may have an reference count > 1
* so Release and nullify the pointer */
hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp ); hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp );
if( hr == S_OK ) l.p_pin_temp->Release(); if( SUCCEEDED( hr ) )
{
l.p_pin_temp->Release();
l.p_pin_temp = NULL;
}
if( hr != VFW_E_NOT_CONNECTED ) if( hr != VFW_E_NOT_CONNECTED )
{ {
if( FAILED( hr ) ) if( FAILED( hr ) )
...@@ -1475,32 +1566,39 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream ) ...@@ -1475,32 +1566,39 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
return hr; return hr;
} }
} }
if(( pin_info_downstream.dir == PINDIR_INPUT ) && if( ( pin_dir == PINDIR_INPUT ) &&
( hr == VFW_E_NOT_CONNECTED ) ) ( hr == VFW_E_NOT_CONNECTED ) )
{ {
hr = p_filter_graph->ConnectDirect( l.p_pin_upstream, hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
l.p_pin_downstream, NULL ); l.p_pin_downstream, NULL );
if( SUCCEEDED( hr ) ) if( SUCCEEDED( hr ) )
{ {
pin_info_downstream.pFilter->Release(); /* If we arrive here then we have a matching pair of
pin_info_upstream.pFilter->Release(); * pins. */
return S_OK; return S_OK;
} }
} }
/* If we fall out here it means this downstream pin was not /* If we arrive here it means this downstream pin is not
* suitable so try the next downstream pin */ * suitable so try the next downstream pin.
l.p_pin_downstream = NULL; * l.p_pin_downstream is released at the top of the loop */
pin_info_downstream.pFilter->Release();
} }
while( true );
/* If we arrive here then we ran out of pins before we found a
* suitable one. Release outstanding refcounts */
if( l.p_pin_downstream_enum )
l.p_pin_downstream_enum->Release();
l.p_pin_downstream_enum = NULL;
if( l.p_pin_downstream )
l.p_pin_downstream->Release();
l.p_pin_downstream = NULL;
} }
/* If we arrive here it means this upstream pin is not suitable
/* If we fall out here it means we did not find any suitable downstream * so try the next upstream pin
* pin so try the next upstream pin */ * l.p_pin_upstream is released at the top of the loop */
l.p_pin_upstream = NULL;
pin_info_upstream.pFilter->Release();
} }
while( true );
/* If we fall out here it means we did not find any pair of suitable pins */ /* If we arrive here it means we did not find any pair of suitable pins
* Outstanding refcounts are released in the destructor */
return E_FAIL; return E_FAIL;
} }
...@@ -1633,10 +1731,34 @@ STDMETHODIMP BDAGraph::BufferCB( double d_time, BYTE* p_buffer, ...@@ -1633,10 +1731,34 @@ STDMETHODIMP BDAGraph::BufferCB( double d_time, BYTE* p_buffer,
HRESULT BDAGraph::Destroy() HRESULT BDAGraph::Destroy()
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
ULONG ul_refcount = 0;
if( p_media_control ) if( p_media_control )
hr = p_media_control->Stop(); hr = p_media_control->Stop();
if( d_graph_register )
{
Deregister();
}
/* We need to empty the buffers of any unprocessed data */
msg_Dbg( p_access, "Queue sample size = %d", queue_sample.size() );
while( !queue_sample.empty() )
{
ul_refcount = queue_sample.front()->Release();
queue_sample.pop();
if( ul_refcount )
msg_Warn( p_access, "BDAGraph: Non-zero Ref: %d", ul_refcount );
}
msg_Dbg( p_access, "Queue buffer size = %d", queue_buffer.size() );
while( !queue_buffer.empty() )
{
ul_refcount = queue_buffer.front()->Release();
queue_buffer.pop();
if( ul_refcount )
msg_Warn( p_access, "BDAGraph: Non-zero Ref: %d", ul_refcount );
}
if( p_transport_info ) if( p_transport_info )
{ {
p_filter_graph->RemoveFilter( p_transport_info ); p_filter_graph->RemoveFilter( p_transport_info );
...@@ -1667,6 +1789,11 @@ HRESULT BDAGraph::Destroy() ...@@ -1667,6 +1789,11 @@ HRESULT BDAGraph::Destroy()
p_tuner_device->Release(); p_tuner_device->Release();
p_tuner_device = NULL; p_tuner_device = NULL;
} }
if( p_scanning_tuner )
{
p_scanning_tuner->Release();
p_scanning_tuner = NULL;
}
if( p_network_provider ) if( p_network_provider )
{ {
p_filter_graph->RemoveFilter( p_network_provider ); p_filter_graph->RemoveFilter( p_network_provider );
...@@ -1674,11 +1801,6 @@ HRESULT BDAGraph::Destroy() ...@@ -1674,11 +1801,6 @@ HRESULT BDAGraph::Destroy()
p_network_provider = NULL; p_network_provider = NULL;
} }
if( p_scanning_tuner )
{
p_scanning_tuner->Release();
p_scanning_tuner = NULL;
}
if( p_media_control ) if( p_media_control )
{ {
p_media_control->Release(); p_media_control->Release();
...@@ -1689,10 +1811,10 @@ HRESULT BDAGraph::Destroy() ...@@ -1689,10 +1811,10 @@ HRESULT BDAGraph::Destroy()
p_filter_graph->Release(); p_filter_graph->Release();
p_filter_graph = NULL; p_filter_graph = NULL;
} }
if( p_system_dev_enum )
if( d_graph_register )
{ {
Deregister(); p_system_dev_enum->Release();
p_system_dev_enum = NULL;
} }
return S_OK; return S_OK;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
***************************************************************************** *****************************************************************************
* Copyright ( C ) 2007 the VideoLAN team * Copyright ( C ) 2007 the VideoLAN team
* *
* Author: Ken Self <kens@campoz.fslife.co.uk> * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -48,6 +48,7 @@ using namespace std; ...@@ -48,6 +48,7 @@ using namespace std;
#include <dshow.h> #include <dshow.h>
#include <comcat.h> #include <comcat.h>
#include <ks.h>
#include "bdadefs.h" #include "bdadefs.h"
#include "bda.h" #include "bda.h"
...@@ -67,10 +68,11 @@ public: ...@@ -67,10 +68,11 @@ public:
private: private:
/* ISampleGrabberCB methods */ /* ISampleGrabberCB methods */
STDMETHODIMP_( ULONG ) AddRef( ) { return 1; } ULONG ul_cbrc;
STDMETHODIMP_( ULONG ) Release( ) { return 2; } STDMETHODIMP_( ULONG ) AddRef( ) { return ++ul_cbrc; }
STDMETHODIMP_( ULONG ) Release( ) { return --ul_cbrc; }
STDMETHODIMP QueryInterface( REFIID riid, void** p_p_object ) STDMETHODIMP QueryInterface( REFIID riid, void** p_p_object )
{return E_NOTIMPL; } { return E_NOTIMPL; }
STDMETHODIMP SampleCB( double d_time, IMediaSample* p_sample ); STDMETHODIMP SampleCB( double d_time, IMediaSample* p_sample );
STDMETHODIMP BufferCB( double d_time, BYTE* p_buffer, long l_buffer_len ); STDMETHODIMP BufferCB( double d_time, BYTE* p_buffer, long l_buffer_len );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment