[vlc-devel] [PATCH 3/3] dtv: Thorough rewrite of BDA graph for Win32
John Freed
okvlc at johnfreed.com
Thu Mar 15 21:54:29 CET 2012
Changes approach to be based on tuner, rather than Windows registry.
---
modules/access/dtv/access.c | 14 +-
modules/access/dtv/bdadefs.h | 23 +-
modules/access/dtv/bdagraph.cpp | 2005 ++++++++++++++++++++++++++++-----------
modules/access/dtv/bdagraph.hpp | 33 +-
modules/access/dtv/dtv.h | 3 +
5 files changed, 1537 insertions(+), 541 deletions(-)
diff --git a/modules/access/dtv/access.c b/modules/access/dtv/access.c
index 624cb76..18dd216 100644
--- a/modules/access/dtv/access.c
+++ b/modules/access/dtv/access.c
@@ -650,12 +650,12 @@ static const delsys_t *GuessSystem (const char *scheme, dvb_device_t *dev)
return NULL;
}
+
/** Set parameters and tune the device */
static int Tune (vlc_object_t *obj, dvb_device_t *dev, const delsys_t *delsys,
uint64_t freq)
{
if (delsys->setup (obj, dev, freq)
- || dvb_set_inversion (dev, var_InheritInteger (obj, "dvb-inversion"))
|| dvb_tune (dev))
return VLC_EGENERIC;
return VLC_SUCCESS;
@@ -840,6 +840,12 @@ static int sec_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
return dvb_set_sec (dev, freq, pol, lowf, highf, switchf);
}
+static int inversion_setup (vlc_object_t *obj, dvb_device_t *dev )
+{
+ int inversion = var_InheritInteger (obj, "dvb-inversion");
+ return dvb_set_inversion (dev, inversion);
+}
+
static int dvbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
{
uint32_t fec = var_InheritCodeRate (obj, "dvb-fec");
@@ -848,6 +854,8 @@ static int dvbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
int ret = dvb_set_dvbs (dev, freq, srate, fec);
if (ret == 0)
ret = sec_setup (obj, dev, freq);
+ if (ret == 0)
+ ret = inversion_setup (obj, dev);
return ret;
}
@@ -862,6 +870,8 @@ static int dvbs2_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
int ret = dvb_set_dvbs2 (dev, freq, mod, srate, fec, pilot, rolloff);
if (ret == 0)
ret = sec_setup (obj, dev, freq);
+ if (ret == 0)
+ ret = inversion_setup (obj, dev);
return ret;
}
@@ -919,6 +929,8 @@ static int isdbs_setup (vlc_object_t *obj, dvb_device_t *dev, uint64_t freq)
int ret = dvb_set_isdbs (dev, freq, ts_id);
if (ret == 0)
ret = sec_setup (obj, dev, freq);
+ if (ret == 0)
+ ret = inversion_setup (obj, dev);
return ret;
}
diff --git a/modules/access/dtv/bdadefs.h b/modules/access/dtv/bdadefs.h
index 79b85c2..8d9e54b 100644
--- a/modules/access/dtv/bdadefs.h
+++ b/modules/access/dtv/bdadefs.h
@@ -48,6 +48,7 @@ class ISampleGrabber;
class ISampleGrabberCB;
class IScanningTuner;
class ITuner;
+class ITunerCap;
class ITuneRequest;
class ITuningSpace;
class ITuningSpaceContainer;
@@ -313,6 +314,19 @@ public:
virtual HRESULT __stdcall Clone( IEnumTuningSpaces** p_p_enum )=0;
};
+class ITunerCap : public IUnknown
+{
+public:
+ virtual HRESULT __stdcall get_AuxInputCount( ULONG* pulCompositeCount,
+ ULONG* pulSvideoCount )=0;
+ virtual HRESULT __stdcall get_SupportedNetworkTypes(
+ ULONG ulcNetworkTypesMax, ULONG* pulcNetworkTypes,
+ GUID* pguidNetworkTypes )=0;
+ virtual HRESULT __stdcall get_SupportedVideoFormats(
+ ULONG* pulAMTunerModeType, ULONG* pulAnalogVideoStandard )=0;
+};
+
+
class ITuner : public IUnknown
{
public:
@@ -664,7 +678,7 @@ public:
virtual HRESULT __stdcall CreateTopology( ULONG ulInputPinId,
ULONG ulOutputPinId )=0;
virtual HRESULT __stdcall GetControlNode( ULONG ulInputPinId,
- ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode )=0;
+ ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode )=0;
};
typedef struct _MPEG_HEADER_BITS_MIDL
@@ -955,6 +969,8 @@ const IID IID_IDigitalCableLocator =
{0x48F66A11,0x171A,0x419A,{0x95,0x25,0xBE,0xEE,0xCD,0x51,0x58,0x4C}};
/* KSCATEGORY_BDA */
+const GUID KSCATEGORY_BDA_NETWORK_PROVIDER =
+ {0x71985F4B,0x1CA1,0x11d3,{0x9C,0xC8,0x00,0xC0,0x4F,0x79,0x71,0xE0}};
const GUID KSCATEGORY_BDA_TRANSPORT_INFORMATION =
{0xa2e3074f,0x6c3d,0x11d3,{0xb6,0x53,0x00,0xc0,0x4f,0x79,0x49,0x8e}};
const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT =
@@ -1007,6 +1023,10 @@ extern const IID IID_IMpeg2Demultiplexer;
extern const IID IID_ISampleGrabber;
extern const IID IID_IScanningTuner;
extern const IID IID_ITuner;
+/* Following symbol does not exist in library
+extern const IID IID_ITunerCap; */
+const IID IID_ITunerCap =
+ {0xE60DFA45,0x8D56,0x4e65,{0xA8,0xAB,0xD6,0xBE,0x94,0x12,0xC2,0x49}};
extern const IID IID_ITuningSpace;
extern const IID IID_ITuningSpaceContainer;
/* Following symbol does not exist in library
@@ -1026,4 +1046,5 @@ extern const GUID MEDIASUBTYPE_MPEG2_TRANSPORT;
extern const GUID MEDIASUBTYPE_None;
extern const GUID FORMAT_None;
+
};
diff --git a/modules/access/dtv/bdagraph.cpp b/modules/access/dtv/bdagraph.cpp
index 5ef3ac5..712c0fc 100644
--- a/modules/access/dtv/bdagraph.cpp
+++ b/modules/access/dtv/bdagraph.cpp
@@ -3,13 +3,14 @@
*****************************************************************************
* Copyright (C) 2007 the VideoLAN team
* Copyright (C) 2011 Rémi Denis-Courmont
+ * Copyright (C) 2012 John Freed
*
* Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
*
* 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.
+ * ( 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
@@ -32,6 +33,7 @@
#include <vlc_block.h>
#include "dtv/bdagraph.hpp"
#include "dtv/dtv.h"
+#undef DEBUG_MONIKER_NAME
static ModulationType dvb_parse_modulation (const char *mod)
@@ -164,10 +166,16 @@ void dvb_remove_pid (dvb_device_t *, uint16_t)
{
}
-unsigned dvb_enum_systems (dvb_device_t *)
+unsigned dvb_enum_systems (dvb_device_t *d)
{
-#warning TODO
- return 0;
+//debug
+ vlc_mutex_t lock;
+ vlc_cond_t wait;
+ vlc_mutex_init( &lock );
+ vlc_cond_init( &wait );
+ return d->module->EnumSystems( );
+ vlc_mutex_destroy( &lock );
+ vlc_cond_destroy( &wait );
}
float dvb_get_signal_strength (dvb_device_t *)
@@ -183,8 +191,6 @@ float dvb_get_snr (dvb_device_t *)
int dvb_set_inversion (dvb_device_t *d, int inversion)
{
d->inversion = inversion;
- if (d->frequency == 0)
- return 0; /* not DVB-S */
return d->module->SetDVBS(d->frequency, d->srate, d->fec, d->inversion,
d->pol, d->lowf, d->highf, d->switchf);
}
@@ -277,7 +283,6 @@ int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char * /*mod*/)
return d->module->SetCQAM(freq / 1000);
}
-
/*****************************************************************************
* BDAOutput
*****************************************************************************/
@@ -358,12 +363,14 @@ BDAGraph::BDAGraph( vlc_object_t *p_this ):
p_access( p_this ),
guid_network_type(GUID_NULL),
l_tuner_used(-1),
+ systems(0),
d_graph_register( 0 ),
output( p_this )
{
- p_tuning_space = NULL;
- p_tune_request = NULL;
p_media_control = NULL;
+
+ p_tuning_space = NULL;
+
p_filter_graph = NULL;
p_system_dev_enum = NULL;
p_network_provider = p_tuner_device = p_capture_device = NULL;
@@ -382,35 +389,117 @@ BDAGraph::BDAGraph( vlc_object_t *p_this ):
BDAGraph::~BDAGraph()
{
Destroy();
+
+ if( p_tuning_space )
+ p_tuning_space->Release();
+ p_tuning_space = NULL;
+
+ systems = 0;
CoUninitialize();
}
+/*****************************************************************************
+* GetSystem
+* helper function
+*****************************************************************************/
+unsigned BDAGraph::GetSystem( REFCLSID clsid )
+{
+ unsigned sys = 0;
+
+ if( clsid == CLSID_DVBTNetworkProvider )
+ sys = DVB_T;
+ if( clsid == CLSID_DVBCNetworkProvider )
+ sys = DVB_C;
+ if( clsid == CLSID_DVBSNetworkProvider )
+ sys = DVB_S;
+ if( clsid == CLSID_ATSCNetworkProvider )
+ sys = ATSC;
+ if( clsid == CLSID_DigitalCableNetworkType )
+ sys = CQAM;
+ if( clsid == CLSID_NetworkProvider )
+ sys = UNIVERSAL;
+ return sys;
+}
+
+
+/*****************************************************************************
+ * Enumerate Systems
+ *****************************************************************************
+ * here is logic for special case where user uses an MRL that points
+ * to DTV but is not fully specific. This is usually dvb:// and can come
+ * either from a playlist, a channels.conf MythTV file, or from manual entry.
+ *
+ * Since this is done before the real tune request is submitted, we can
+ * use the global device enumerator, etc., so long as we do a Destroy() at
+ * the end
+ *****************************************************************************/
+unsigned BDAGraph::EnumSystems()
+{
+ HRESULT hr = S_OK;
+ GUID guid_network_provider = GUID_NULL;
+
+ msg_Dbg( p_access, "EnumSystems: Entering EnumSystems 0314 10:45pm" );
+
+ do
+ {
+ hr = GetNextNetworkType( &guid_network_provider );
+ if( hr != S_OK ) break;
+ hr = Check( guid_network_provider );
+ if( FAILED( hr ) )
+ msg_Dbg( p_access, "EnumSystems: Check failed, trying next" );
+ }
+ while( true );
+
+ if( p_filter_graph )
+ Destroy();
+ msg_Dbg( p_access, "EnumSystems: Returning systems 0x%08x", systems );
+ return systems;
+}
+
int BDAGraph::SubmitTuneRequest(void)
{
HRESULT hr;
+ int i = 0;
- /* Build and Run the Graph. If a Tuner device is in use the graph will
- * fail to run. Repeated calls to build will check successive tuner
+ /* Build and Start the Graph. If a Tuner device is in use the graph will
+ * fail to start. Repeated calls to Build will check successive tuner
* devices */
do
{
+ msg_Dbg( p_access, "SubmitTuneRequest: Building the Graph" );
+
hr = Build();
if( FAILED( hr ) )
{
msg_Warn( p_access, "SubmitTuneRequest: "
- "Cannot Build the Graph: hr=0x%8lx", hr );
+ "Cannot Build the Graph: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+ msg_Dbg( p_access, "SubmitTuneRequest: Starting the Graph" );
hr = Start();
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SubmitTuneRequest: "
+ "Cannot Start the Graph, retrying: hr=0x%8lx", hr );
+ ++i;
+ }
+ }
+ while( hr != S_OK && i < 10 ); /* give up after 10 tries */
+
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SubmitTuneRequest: "
+ "Failed to Start the Graph: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
}
- while( hr != S_OK );
return VLC_SUCCESS;
}
/*****************************************************************************
-* Set clear QAM (US cable)
+* Set Clear QAM (DigitalCable)
+* Local ATSC Digital Antenna
*****************************************************************************/
int BDAGraph::SetCQAM(long l_frequency)
{
@@ -418,11 +507,18 @@ int BDAGraph::SetCQAM(long l_frequency)
class localComPtr
{
public:
- IDigitalCableTuneRequest* p_cqam_tune_request;
- IDigitalCableLocator* p_cqam_locator;
- localComPtr(): p_cqam_tune_request(NULL), p_cqam_locator(NULL) {};
+ ITuneRequest* p_tune_request;
+ IDigitalCableTuneRequest* p_cqam_tune_request;
+ IDigitalCableLocator* p_cqam_locator;
+ localComPtr():
+ p_tune_request(NULL),
+ p_cqam_tune_request(NULL),
+ p_cqam_locator(NULL)
+ {};
~localComPtr()
{
+ if( p_tune_request )
+ p_tune_request->Release();
if( p_cqam_tune_request )
p_cqam_tune_request->Release();
if( p_cqam_locator )
@@ -434,28 +530,43 @@ int BDAGraph::SetCQAM(long l_frequency)
l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
- guid_network_type = CLSID_DigitalCableNetworkType;
- hr = CreateTuneRequest();
+ /* try to set p_scanning_tuner */
+ hr = Check( CLSID_DigitalCableNetworkType );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitCQAMTuneRequest: "\
- "Cannot create Tuning Space: hr=0x%8lx", hr );
+ msg_Warn( p_access, "SetCQAM: "\
+ "Cannot create Tuning Space: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetCQAM: Cannot get scanning tuner" );
+ return VLC_EGENERIC;
+ }
+
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetCQAM: "\
+ "Cannot get Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->QueryInterface( IID_IDigitalCableTuneRequest,
- (void**)&l.p_cqam_tune_request );
+ hr = l.p_tune_request->QueryInterface( IID_IDigitalCableTuneRequest,
+ reinterpret_cast<void**>( &l.p_cqam_tune_request ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitCQAMTuneRequest: "\
+ msg_Warn( p_access, "SetCQAM: "\
"Cannot QI for IDigitalCableTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+
hr = ::CoCreateInstance( CLSID_DigitalCableLocator, 0, CLSCTX_INPROC,
- IID_IDigitalCableLocator, (void**)&l.p_cqam_locator );
+ IID_IDigitalCableLocator, reinterpret_cast<void**>( &l.p_cqam_locator ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitCQAMTuneRequest: "\
+ msg_Warn( p_access, "SetCQAM: "\
"Cannot create the CQAM locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
@@ -469,19 +580,34 @@ int BDAGraph::SetCQAM(long l_frequency)
hr = l.p_cqam_tune_request->put_MinorChannel( l_minor_channel );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitCQAMTuneRequest: "\
+ msg_Warn( p_access, "SetCQAM: "\
"Cannot set tuning parameters: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->put_Locator( l.p_cqam_locator );
+ hr = l.p_cqam_tune_request->put_Locator( l.p_cqam_locator );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitCQAMTuneRequest: "\
+ msg_Warn( p_access, "SetCQAM: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+ hr = p_scanning_tuner->Validate( l.p_cqam_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetCQAM: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_cqam_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetCQAM: "\
+ "Cannot put the tune request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
return VLC_SUCCESS;
}
@@ -494,11 +620,18 @@ int BDAGraph::SetATSC(long l_frequency)
class localComPtr
{
public:
- IATSCChannelTuneRequest* p_atsc_tune_request;
- IATSCLocator* p_atsc_locator;
- localComPtr(): p_atsc_tune_request(NULL), p_atsc_locator(NULL) {};
+ ITuneRequest* p_tune_request;
+ IATSCChannelTuneRequest* p_atsc_tune_request;
+ IATSCLocator* p_atsc_locator;
+ localComPtr():
+ p_tune_request(NULL),
+ p_atsc_tune_request(NULL),
+ p_atsc_locator(NULL)
+ {};
~localComPtr()
{
+ if( p_tune_request )
+ p_tune_request->Release();
if( p_atsc_tune_request )
p_atsc_tune_request->Release();
if( p_atsc_locator )
@@ -507,32 +640,48 @@ int BDAGraph::SetATSC(long l_frequency)
} l;
long l_major_channel, l_minor_channel, l_physical_channel;
+ /* fixme: these parameters should have dtv prefix, not dvb */
l_major_channel = var_GetInteger( p_access, "dvb-major-channel" );
l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
- guid_network_type = CLSID_ATSCNetworkProvider;
- hr = CreateTuneRequest();
+ /* try to set p_scanning_tuner */
+ hr = Check( CLSID_ATSCNetworkProvider );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitATSCTuneRequest: "\
+ msg_Warn( p_access, "SetATSC: "\
"Cannot create Tuning Space: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->QueryInterface( IID_IATSCChannelTuneRequest,
- (void**)&l.p_atsc_tune_request );
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetATSC: Cannot get scanning tuner" );
+ return VLC_EGENERIC;
+ }
+
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitATSCTuneRequest: "\
+ msg_Warn( p_access, "SetATSC: "\
+ "Cannot get Tune Request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ hr = l.p_tune_request->QueryInterface( IID_IATSCChannelTuneRequest,
+ reinterpret_cast<void**>( &l.p_atsc_tune_request ) );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetATSC: "\
"Cannot QI for IATSCChannelTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+
hr = ::CoCreateInstance( CLSID_ATSCLocator, 0, CLSCTX_INPROC,
- IID_IATSCLocator, (void**)&l.p_atsc_locator );
+ IID_IATSCLocator, reinterpret_cast<void**>( &l.p_atsc_locator ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitATSCTuneRequest: "\
+ msg_Warn( p_access, "SetATSC: "\
"Cannot create the ATSC locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
@@ -548,40 +697,74 @@ int BDAGraph::SetATSC(long l_frequency)
hr = l.p_atsc_locator->put_PhysicalChannel( l_physical_channel );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitATSCTuneRequest: "\
+ msg_Warn( p_access, "SetATSC: "\
"Cannot set tuning parameters: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->put_Locator( l.p_atsc_locator );
+ hr = l.p_atsc_tune_request->put_Locator( l.p_atsc_locator );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitATSCTuneRequest: "\
+ msg_Warn( p_access, "SetATSC: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+
+ hr = p_scanning_tuner->Validate( l.p_atsc_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetATSC: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_atsc_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetATSC: "\
+ "Cannot put the tune request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
return VLC_SUCCESS;
}
/*****************************************************************************
* Set DVB-T
+*
+* This provides the tune request that everything else is built upon.
+*
+* By rights this should call dvb_tune as well, because theoretically another
+* tune request could intervene between setdvbt and dvb_tune, so you probably
+* need a mutex lock in access.c to prevent this. However, it calls setdvbt
+* and dvb_tune in quick order, so this probably never arises in practice
+*
+* Stores the tune request to the scanning tuner, where it is pulled out by
+* dvb_tune a/k/a SubmitTuneRequest.
******************************************************************************/
int BDAGraph::SetDVBT(long l_frequency, uint32_t fec_hp, uint32_t fec_lp,
long l_bandwidth, int transmission, uint32_t guard, int hierarchy)
{
HRESULT hr = S_OK;
+
class localComPtr
{
public:
- IDVBTuneRequest* p_dvbt_tune_request;
- IDVBTLocator* p_dvbt_locator;
- IDVBTuningSpace2* p_dvb_tuning_space;
- localComPtr(): p_dvbt_tune_request(NULL), p_dvbt_locator(NULL),
- p_dvb_tuning_space(NULL) {};
+ ITuneRequest* p_tune_request;
+ IDVBTuneRequest* p_dvb_tune_request;
+ IDVBTLocator* p_dvbt_locator;
+ IDVBTuningSpace2* p_dvb_tuning_space;
+ localComPtr():
+ p_tune_request(NULL),
+ p_dvb_tune_request(NULL),
+ p_dvbt_locator(NULL),
+ p_dvb_tuning_space(NULL)
+ {};
~localComPtr()
{
- if( p_dvbt_tune_request )
- p_dvbt_tune_request->Release();
+ if( p_tune_request )
+ p_tune_request->Release();
+ if( p_dvb_tune_request )
+ p_dvb_tune_request->Release();
if( p_dvbt_locator )
p_dvbt_locator->Release();
if( p_dvb_tuning_space )
@@ -589,53 +772,82 @@ int BDAGraph::SetDVBT(long l_frequency, uint32_t fec_hp, uint32_t fec_lp,
}
} l;
+ /* create local dvbt-specific tune request and locator
+ * then put it to existing scanning tuner */
BinaryConvolutionCodeRate i_hp_fec = dvb_parse_fec(fec_hp);
BinaryConvolutionCodeRate i_lp_fec = dvb_parse_fec(fec_lp);
GuardInterval i_guard = dvb_parse_guard(guard);
TransmissionMode i_transmission = dvb_parse_transmission(transmission);
HierarchyAlpha i_hierarchy = dvb_parse_hierarchy(hierarchy);
- guid_network_type = CLSID_DVBTNetworkProvider;
- hr = CreateTuneRequest();
+ /* try to set p_scanning_tuner */
+ //msg_Dbg( p_access, "SetDVBT: set up scanning tuner" );
+ hr = Check( CLSID_DVBTNetworkProvider );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBT: "\
+ "Cannot create Tuning Space: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetDVBT: Cannot get scanning tuner" );
+ return VLC_EGENERIC;
+ }
+
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
- "Cannot create Tune Request: hr=0x%8lx", hr );
+ msg_Warn( p_access, "SetDVBT: "\
+ "Cannot get Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
- (void**)&l.p_dvbt_tune_request );
+ //msg_Dbg( p_access, "SetDVBT: Creating DVB tune request" );
+ hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
+ reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
+ msg_Warn( p_access, "SetDVBT: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- l.p_dvbt_tune_request->put_ONID( -1 );
- l.p_dvbt_tune_request->put_SID( -1 );
- l.p_dvbt_tune_request->put_TSID( -1 );
- hr = ::CoCreateInstance( CLSID_DVBTLocator, 0, CLSCTX_INPROC,
- IID_IDVBTLocator, (void**)&l.p_dvbt_locator );
+ l.p_dvb_tune_request->put_ONID( -1 );
+ l.p_dvb_tune_request->put_SID( -1 );
+ l.p_dvb_tune_request->put_TSID( -1 );
+
+ //msg_Dbg( p_access, "SetDVBT: get TS" );
+ hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
- "Cannot create the DVBT Locator: hr=0x%8lx", hr );
+ msg_Dbg( p_access, "SetDVBT: "\
+ "cannot get tuning space: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+
+ //msg_Dbg( p_access, "SetDVBT: QI to DVBT TS" );
hr = p_tuning_space->QueryInterface( IID_IDVBTuningSpace2,
- (void**)&l.p_dvb_tuning_space );
+ reinterpret_cast<void**>( &l.p_dvb_tuning_space ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
+ msg_Warn( p_access, "SetDVBT: "\
"Cannot QI for IDVBTuningSpace2: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = S_OK;
- hr = l.p_dvb_tuning_space->put_SystemType( DVB_Terrestrial );
+ //msg_Dbg( p_access, "SetDVBT: Creating local locator" );
+ hr = ::CoCreateInstance( CLSID_DVBTLocator, 0, CLSCTX_INPROC,
+ IID_IDVBTLocator, reinterpret_cast<void**>( &l.p_dvbt_locator ) );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBT: "\
+ "Cannot create the DVBT Locator: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+ hr = l.p_dvb_tuning_space->put_SystemType( DVB_Terrestrial );
if( SUCCEEDED( hr ) && l_frequency > 0 )
hr = l.p_dvbt_locator->put_CarrierFrequency( l_frequency );
if( SUCCEEDED( hr ) && l_bandwidth > 0 )
@@ -650,21 +862,41 @@ int BDAGraph::SetDVBT(long l_frequency, uint32_t fec_hp, uint32_t fec_lp,
hr = l.p_dvbt_locator->put_Mode( i_transmission );
if( SUCCEEDED( hr ) && i_hierarchy != BDA_HALPHA_NOT_SET )
hr = l.p_dvbt_locator->put_HAlpha( i_hierarchy );
+
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
+ msg_Warn( p_access, "SetDVBT: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->put_Locator( l.p_dvbt_locator );
+ //msg_Dbg( p_access, "SetDVBT: putting DVBT locator into local tune request" );
+
+ hr = l.p_dvb_tune_request->put_Locator( l.p_dvbt_locator );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBTTuneRequest: "\
+ msg_Warn( p_access, "SetDVBT: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+// msg_Dbg( p_access, "SetDVBT: putting local Tune Request to scanning tuner" );
+ hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetDVBT: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBT: "\
+ "Cannot put the tune request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ //msg_Dbg( p_access, "SetDVBT: return success" );
return VLC_SUCCESS;
}
@@ -678,16 +910,23 @@ int BDAGraph::SetDVBC(long l_frequency, const char *mod, long l_symbolrate)
class localComPtr
{
public:
- IDVBTuneRequest* p_dvbc_tune_request;
- IDVBCLocator* p_dvbc_locator;
- IDVBTuningSpace2* p_dvb_tuning_space;
+ ITuneRequest* p_tune_request;
+ IDVBTuneRequest* p_dvb_tune_request;
+ IDVBCLocator* p_dvbc_locator;
+ IDVBTuningSpace2* p_dvb_tuning_space;
- localComPtr(): p_dvbc_tune_request(NULL), p_dvbc_locator(NULL),
- p_dvb_tuning_space(NULL) {};
+ localComPtr():
+ p_tune_request(NULL),
+ p_dvb_tune_request(NULL),
+ p_dvbc_locator(NULL),
+ p_dvb_tuning_space(NULL)
+ {};
~localComPtr()
{
- if( p_dvbc_tune_request )
- p_dvbc_tune_request->Release();
+ if( p_tune_request )
+ p_tune_request->Release();
+ if( p_dvb_tune_request )
+ p_dvb_tune_request->Release();
if( p_dvbc_locator )
p_dvbc_locator->Release();
if( p_dvb_tuning_space )
@@ -697,40 +936,56 @@ int BDAGraph::SetDVBC(long l_frequency, const char *mod, long l_symbolrate)
ModulationType i_qam_mod = dvb_parse_modulation(mod);
- guid_network_type = CLSID_DVBCNetworkProvider;
- hr = CreateTuneRequest();
+ /* try to set p_scanning_tuner */
+ hr = Check( CLSID_DVBCNetworkProvider );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBC: "\
+ "Cannot create Tuning Space: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetDVBC: Cannot get scanning tuner" );
+ return VLC_EGENERIC;
+ }
+
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
- "Cannot create Tune Request: hr=0x%8lx", hr );
+ msg_Warn( p_access, "SetDVBC: "\
+ "Cannot get Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
- (void**)&l.p_dvbc_tune_request );
+ hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
+ reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+ msg_Warn( p_access, "SetDVBC: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- l.p_dvbc_tune_request->put_ONID( -1 );
- l.p_dvbc_tune_request->put_SID( -1 );
- l.p_dvbc_tune_request->put_TSID( -1 );
+
+ l.p_dvb_tune_request->put_ONID( -1 );
+ l.p_dvb_tune_request->put_SID( -1 );
+ l.p_dvb_tune_request->put_TSID( -1 );
hr = ::CoCreateInstance( CLSID_DVBCLocator, 0, CLSCTX_INPROC,
- IID_IDVBCLocator, (void**)&l.p_dvbc_locator );
+ IID_IDVBCLocator, reinterpret_cast<void**>( &l.p_dvbc_locator ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+ msg_Warn( p_access, "SetDVBC: "\
"Cannot create the DVB-C Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+
hr = p_tuning_space->QueryInterface( IID_IDVBTuningSpace2,
- (void**)&l.p_dvb_tuning_space );
+ reinterpret_cast<void**>( &l.p_dvb_tuning_space ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+ msg_Warn( p_access, "SetDVBC: "\
"Cannot QI for IDVBTuningSpace2: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
@@ -747,19 +1002,34 @@ int BDAGraph::SetDVBC(long l_frequency, const char *mod, long l_symbolrate)
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+ msg_Warn( p_access, "SetDVBC: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->put_Locator( l.p_dvbc_locator );
+ hr = l.p_dvb_tune_request->put_Locator( l.p_dvbc_locator );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+ msg_Warn( p_access, "SetDVBC: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+ hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetDVBC: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBC: "\
+ "Cannot put the tune request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
return VLC_SUCCESS;
}
@@ -775,29 +1045,39 @@ int BDAGraph::SetDVBS(long l_frequency, long l_symbolrate, uint32_t fec,
class localComPtr
{
public:
- IDVBTuneRequest* p_dvbs_tune_request;
- IDVBSLocator* p_dvbs_locator;
- IDVBSTuningSpace* p_dvbs_tuning_space;
- char* psz_polarisation;
- char* psz_input_range;
- BSTR bstr_input_range;
- WCHAR* pwsz_input_range;
- int i_range_len;
- localComPtr() : p_dvbs_tune_request(NULL), p_dvbs_locator(NULL),
+ ITuneRequest* p_tune_request;
+ IDVBTuneRequest* p_dvb_tune_request;
+ IDVBSLocator* p_dvbs_locator;
+ IDVBSTuningSpace* p_dvbs_tuning_space;
+ char* psz_polarisation;
+ char* psz_input_range;
+ BSTR bstr_input_range;
+ WCHAR* pwsz_input_range;
+ int i_range_len;
+ localComPtr() :
+ p_tune_request(NULL),
+ p_dvb_tune_request(NULL),
+ p_dvbs_locator(NULL),
p_dvbs_tuning_space(NULL),
- psz_polarisation(NULL), psz_input_range(NULL),
- bstr_input_range(NULL), pwsz_input_range(NULL), i_range_len(0)
+ psz_polarisation(NULL),
+ psz_input_range(NULL),
+ bstr_input_range(NULL),
+ pwsz_input_range(NULL),
+ i_range_len(0)
{}
~localComPtr()
{
- if( p_dvbs_tuning_space )
- p_dvbs_tuning_space->Release();
- if( p_dvbs_tune_request )
- p_dvbs_tune_request->Release();
+ if( p_tune_request )
+ p_tune_request->Release();
+ if( p_dvb_tune_request )
+ p_dvb_tune_request->Release();
if( p_dvbs_locator )
p_dvbs_locator->Release();
+ if( p_dvbs_tuning_space )
+ p_dvbs_tuning_space->Release();
SysFreeString( bstr_input_range );
- delete pwsz_input_range;
+ if( pwsz_input_range )
+ delete[] pwsz_input_range;
free( psz_input_range );
free( psz_polarisation );
}
@@ -815,12 +1095,12 @@ int BDAGraph::SetDVBS(long l_frequency, long l_symbolrate, uint32_t fec,
l_longitude = var_GetInteger( p_access, "dvb-longitude" );
l_network_id = var_GetInteger( p_access, "dvb-network-id" );
- l.psz_input_range = var_GetNonEmptyString( p_access, "dvb-range" );
if( asprintf( &l.psz_polarisation, "%c", pol ) == -1 )
abort();
b_west = ( l_longitude < 0 );
+ l.psz_input_range = var_GetNonEmptyString( p_access, "dvb-range" );
l.i_range_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
l.psz_input_range, -1, l.pwsz_input_range, 0 );
if( l.i_range_len > 0 )
@@ -828,49 +1108,72 @@ int BDAGraph::SetDVBS(long l_frequency, long l_symbolrate, uint32_t fec,
l.pwsz_input_range = new WCHAR[l.i_range_len];
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
l.psz_input_range, -1, l.pwsz_input_range, l.i_range_len );
- l.bstr_input_range=SysAllocString( l.pwsz_input_range );
+ l.bstr_input_range = SysAllocString( l.pwsz_input_range );
+ }
+
+ /* try to set p_scanning_tuner */
+ hr = Check( CLSID_DVBSNetworkProvider );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBS: "\
+ "Cannot create Tuning Space: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetDVBS: Cannot get scanning tuner" );
+ return VLC_EGENERIC;
}
- guid_network_type = CLSID_DVBSNetworkProvider;
- hr = CreateTuneRequest();
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
- "Cannot create Tune Request: hr=0x%8lx", hr );
+ msg_Warn( p_access, "SetDVBS: "\
+ "Cannot get Tune Request: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->QueryInterface( IID_IDVBTuneRequest,
- (void**)&l.p_dvbs_tune_request );
+ hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
+ reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+ msg_Warn( p_access, "SetDVBS: "\
"Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- l.p_dvbs_tune_request->put_ONID( -1 );
- l.p_dvbs_tune_request->put_SID( -1 );
- l.p_dvbs_tune_request->put_TSID( -1 );
+
+ l.p_dvb_tune_request->put_ONID( -1 );
+ l.p_dvb_tune_request->put_SID( -1 );
+ l.p_dvb_tune_request->put_TSID( -1 );
hr = ::CoCreateInstance( CLSID_DVBSLocator, 0, CLSCTX_INPROC,
- IID_IDVBSLocator, (void**)&l.p_dvbs_locator );
+ IID_IDVBSLocator, reinterpret_cast<void**>( &l.p_dvbs_locator ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+ msg_Warn( p_access, "SetDVBS: "\
"Cannot create the DVBS Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+ //msg_Dbg( p_access, "SetDVBS: get TS" );
+ hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetDVBS: "\
+ "cannot get tuning space: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
hr = p_tuning_space->QueryInterface( IID_IDVBSTuningSpace,
- (void**)&l.p_dvbs_tuning_space );
+ reinterpret_cast<void**>( &l.p_dvbs_tuning_space ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+ msg_Warn( p_access, "SetDVBS: "\
"Cannot QI for IDVBSTuningSpace: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = S_OK;
hr = l.p_dvbs_tuning_space->put_SystemType( DVB_Satellite );
if( SUCCEEDED( hr ) && l_lnb_lof1 > 0 )
hr = l.p_dvbs_tuning_space->put_LowOscillator( l_lnb_lof1 );
@@ -904,52 +1207,101 @@ int BDAGraph::SetDVBS(long l_frequency, long l_symbolrate, uint32_t fec,
hr = l.p_dvbs_locator->put_WestPosition( b_west );
if( SUCCEEDED( hr ) )
hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
+
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+ msg_Warn( p_access, "SetDVBS: "\
"Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
- hr = p_tune_request->put_Locator( l.p_dvbs_locator );
+ hr = l.p_dvb_tune_request->put_Locator( l.p_dvbs_locator );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+ msg_Warn( p_access, "SetDVBS: "\
"Cannot put the locator: hr=0x%8lx", hr );
return VLC_EGENERIC;
}
+ hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetDVBS: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "SetDVBS: "\
+ "Cannot put the tune request: hr=0x%8lx", hr );
+ return VLC_EGENERIC;
+ }
+
return VLC_SUCCESS;
}
/*****************************************************************************
-* Load the Tuning Space from System Tuning Spaces according to the
-* Network Type requested
+* SetUpTuner
+******************************************************************************
+* Sets up global p_scanning_tuner and sets guid_network_type according
+* to the Network Type requested.
+*
+* Logic: if tuner is set up and is the right network type, use it.
+* Otherwise, clone an existing matching System Tuning Space if possible.
+* If no matching System Tuning space, create a tuning space from scratch.
+* So we never use a System tuning space.
+*
+* Then sets up a tune request and tries to validate it. Finally, puts
+* tune request and tuning space to tuner
+*
+* on success, sets globals: p_scanning_tuner and guid_network_type
+*
******************************************************************************/
-HRESULT BDAGraph::CreateTuneRequest()
+HRESULT BDAGraph::SetUpTuner( REFCLSID guid_this_network_type )
{
HRESULT hr = S_OK;
- GUID guid_this_network_type;
-
class localComPtr
{
public:
- ITuningSpaceContainer* p_tuning_space_container;
- IEnumTuningSpaces* p_tuning_space_enum;
- ITuningSpace* p_this_tuning_space;
- IDVBTuningSpace2* p_dvb_tuning_space;
- BSTR bstr_name;
- char * psz_network_name;
- char * psz_create_name;
- char * psz_bstr_name;
- WCHAR * wpsz_create_name;
- int i_name_len;
-
- localComPtr(): p_tuning_space_container(NULL),
- p_tuning_space_enum(NULL), p_this_tuning_space(NULL),
- p_dvb_tuning_space(NULL), bstr_name(NULL),
- psz_network_name(NULL), psz_create_name(NULL),
- psz_bstr_name(NULL), wpsz_create_name(NULL), i_name_len(0)
+ ITuningSpaceContainer* p_tuning_space_container;
+ IEnumTuningSpaces* p_tuning_space_enum;
+ ITuningSpace* p_test_tuning_space;
+ ITuneRequest* p_tune_request;
+ IDVBTuneRequest* p_dvb_tune_request;
+
+ IDigitalCableTuneRequest* p_cqam_tune_request;
+ IATSCChannelTuneRequest* p_atsc_tune_request;
+ ILocator* p_locator;
+ IDVBTLocator* p_dvbt_locator;
+ IDVBCLocator* p_dvbc_locator;
+ IDVBSLocator* p_dvbs_locator;
+
+ BSTR bstr_name;
+
+ CLSID guid_test_network_type;
+ char* psz_network_name;
+ char* psz_bstr_name;
+ int i_name_len;
+
+ localComPtr():
+ p_tuning_space_container(NULL),
+ p_tuning_space_enum(NULL),
+ p_test_tuning_space(NULL),
+ p_tune_request(NULL),
+ p_dvb_tune_request(NULL),
+ p_cqam_tune_request(NULL),
+ p_atsc_tune_request(NULL),
+ p_locator(NULL),
+ p_dvbt_locator(NULL),
+ p_dvbc_locator(NULL),
+ p_dvbs_locator(NULL),
+ bstr_name(NULL),
+ guid_test_network_type(GUID_NULL),
+ psz_network_name(NULL),
+ psz_bstr_name(NULL),
+ i_name_len(0)
{}
~localComPtr()
{
@@ -957,27 +1309,44 @@ HRESULT BDAGraph::CreateTuneRequest()
p_tuning_space_enum->Release();
if( p_tuning_space_container )
p_tuning_space_container->Release();
- if( p_this_tuning_space )
- p_this_tuning_space->Release();
- if( p_dvb_tuning_space )
- p_dvb_tuning_space->Release();
+ if( p_test_tuning_space )
+ p_test_tuning_space->Release();
+ if( p_tune_request )
+ p_tune_request->Release();
+ if( p_dvb_tune_request )
+ p_dvb_tune_request->Release();
+ if( p_cqam_tune_request )
+ p_cqam_tune_request->Release();
+ if( p_atsc_tune_request )
+ p_atsc_tune_request->Release();
+ if( p_locator )
+ p_locator->Release();
+ if( p_dvbt_locator )
+ p_dvbt_locator->Release();
+ if( p_dvbc_locator )
+ p_dvbc_locator->Release();
+ if( p_dvbs_locator )
+ p_dvbs_locator->Release();
SysFreeString( bstr_name );
delete[] psz_bstr_name;
- delete[] wpsz_create_name;
free( psz_network_name );
- free( psz_create_name );
}
} l;
+ msg_Dbg( p_access, "SetUpTuner: entering" );
+
+
/* We shall test for a specific Tuning space name supplied on the command
- * line as dvb-networkname=xxx.
+ * line as dvb-network-name=xxx.
* For some users with multiple cards and/or multiple networks this could
* be useful. This allows us to reasonably safely apply updates to the
* System Tuning Space in the registry without disrupting other streams. */
+
l.psz_network_name = var_GetNonEmptyString( p_access, "dvb-network-name" );
+
if( l.psz_network_name )
{
- msg_Dbg( p_access, "CreateTuneRequest: Find Tuning Space: %s",
+ msg_Dbg( p_access, "SetUpTuner: Find Tuning Space: %s",
l.psz_network_name );
}
else
@@ -986,274 +1355,297 @@ HRESULT BDAGraph::CreateTuneRequest()
*l.psz_network_name = '\0';
}
- /* A Tuning Space may already have been set up. If it is for the same
+ /* Tuner may already have been set up. If it is for the same
* network type then all is well. Otherwise, reset the Tuning Space and get
* a new one */
+ //msg_Dbg( p_access, "SetUpTuner: Checking for tuning space" );
+ if( !p_scanning_tuner )
+ {
+ msg_Warn( p_access, "SetUpTuner: "\
+ "Cannot find scanning tuner" );
+ return E_FAIL;
+ }
+
if( p_tuning_space )
{
- hr = p_tuning_space->get__NetworkType( &guid_this_network_type );
- if( FAILED( hr ) ) guid_this_network_type = GUID_NULL;
- if( guid_this_network_type == guid_network_type )
+ //msg_Dbg( p_access, "SetUpTuner: get network type" );
+ hr = p_tuning_space->get__NetworkType( &l.guid_test_network_type );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Check: "\
+ "Cannot get network type: hr=0x%8lx", hr );
+ l.guid_test_network_type = GUID_NULL;
+ }
+
+ //msg_Dbg( p_access, "SetUpTuner: see if it's the right one" );
+ if( l.guid_test_network_type == guid_this_network_type )
{
+ //msg_Dbg( p_access, "SetUpTuner: it's the right one" );
+ SysFreeString( l.bstr_name );
+
hr = p_tuning_space->get_UniqueName( &l.bstr_name );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "CreateTuneRequest: "\
+ /* should never fail on a good tuning space */
+ msg_Dbg( p_access, "SetUpTuner: "\
"Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
- return hr;
+ goto NoTuningSpace;
}
+
+ /* Test for a specific Tuning space name supplied on the command
+ * line as dvb-network-name=xxx */
+ if( l.psz_bstr_name )
+ delete[] l.psz_bstr_name;
l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
l.psz_bstr_name, 0, NULL, NULL );
l.psz_bstr_name = new char[ l.i_name_len ];
l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
l.psz_bstr_name, l.i_name_len, NULL, NULL );
- /* Test for a specific Tuning space name supplied on the command
- * line as dvb-networkname=xxx */
+ /* if no name was requested on command line, or if the name
+ * requested equals the name of this space, we are OK */
if( *l.psz_network_name == '\0' ||
strcmp( l.psz_network_name, l.psz_bstr_name ) == 0 )
{
- msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %s",
- l.psz_network_name );
- return S_OK;
+ msg_Dbg( p_access, "SetUpTuner: Using Tuning Space: %s",
+ l.psz_bstr_name );
+ /* p_tuning_space and guid_network_type are already set */
+ /* you probably already have a tune request, also */
+ hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
+ if( SUCCEEDED( hr ) )
+ {
+ return S_OK;
+ }
+ /* CreateTuneRequest adds l.p_tune_request to p_tuning_space
+ * l.p_tune_request->RefCount = 1 */
+ hr = p_tuning_space->CreateTuneRequest( &l.p_tune_request );
+ if( SUCCEEDED( hr ) )
+ {
+ return S_OK;
+ }
+ msg_Warn( p_access, "SetUpTuner: "\
+ "Cannot Create Tune Request: hr=0x%8lx", hr );
+ /* fall through to NoTuningSpace */
}
}
+
/* else different guid_network_type */
+ NoTuningSpace:
if( p_tuning_space )
p_tuning_space->Release();
- if( p_tune_request )
- p_tune_request->Release();
p_tuning_space = NULL;
- p_tune_request = NULL;
+ /* pro forma; should have returned S_OK if we created this */
+ if( l.p_tune_request )
+ l.p_tune_request->Release();
+ l.p_tune_request = NULL;
}
- /* Force use of the first available Tuner Device during Build */
- l_tuner_used = -1;
- /* Get the SystemTuningSpaces container to enumerate through all the
- * defined tuning spaces.
- * l.p_tuning_space_container->Refcount = 1 */
- hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
- IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot CoCreate SystemTuningSpaces: hr=0x%8lx", hr );
- return hr;
- }
+ /* p_tuning_space is null at this point; we have already
+ returned S_OK if it was good. So find a tuning
+ space on the scanning tuner. */
- /* 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(
- &l.p_tuning_space_enum );
+ //msg_Dbg( p_access, "SetUpTuner: release TuningSpaces Enumerator" );
+ if( l.p_tuning_space_enum )
+ l.p_tuning_space_enum->Release();
+ //msg_Dbg( p_access, "SetUpTuner: nullify TuningSpaces Enumerator" );
+ l.p_tuning_space_enum = NULL;
+ //msg_Dbg( p_access, "SetUpTuner: create TuningSpaces Enumerator" );
+
+ hr = p_scanning_tuner->EnumTuningSpaces( &l.p_tuning_space_enum );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot create SystemTuningSpaces Enumerator: hr=0x%8lx", hr );
- return hr;
+ msg_Warn( p_access, "SetUpTuner: "\
+ "Cannot create TuningSpaces Enumerator: hr=0x%8lx", hr );
+ goto TryToClone;
}
do
{
- /* 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;
+ //msg_Dbg( p_access, "SetUpTuner: top of loop" );
+ l.guid_test_network_type = GUID_NULL;
+ if( l.p_test_tuning_space )
+ l.p_test_tuning_space->Release();
+ l.p_test_tuning_space = NULL;
+ if( p_tuning_space )
+ p_tuning_space->Release();
+ p_tuning_space = NULL;
SysFreeString( l.bstr_name );
-
- hr = l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL );
+ //msg_Dbg( p_access, "SetUpTuner: need good TS enum" );
+ if( !l.p_tuning_space_enum ) break;
+ //msg_Dbg( p_access, "SetUpTuner: next tuning space" );
+ hr = l.p_tuning_space_enum->Next( 1, &l.p_test_tuning_space, NULL );
if( hr != S_OK ) break;
+ //msg_Dbg( p_access, "SetUpTuner: get network type" );
+ hr = l.p_test_tuning_space->get__NetworkType( &l.guid_test_network_type );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Check: "\
+ "Cannot get network type: hr=0x%8lx", hr );
+ l.guid_test_network_type = GUID_NULL;
+ }
+ if( l.guid_test_network_type == guid_this_network_type )
+ {
+ //msg_Dbg( p_access, "SetUpTuner: Found matching space on tuner" );
- hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
-
- /* GUID_NULL means a non-BDA network was found e.g analog
- * Ignore failures and non-BDA networks and keep looking */
- if( FAILED( hr ) ) guid_this_network_type == GUID_NULL;
+ SysFreeString( l.bstr_name );
+ //msg_Dbg( p_access, "SetUpTuner: get unique name" );
- 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->Clone( &p_tuning_space );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot QI Tuning Space: hr=0x%8lx", hr );
- return hr;
- }
- hr = p_tuning_space->get_UniqueName( &l.bstr_name );
+ hr = l.p_test_tuning_space->get_UniqueName( &l.bstr_name );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "CreateTuneRequest: "\
+ /* should never fail on a good tuning space */
+ msg_Dbg( p_access, "SetUpTuner: "\
"Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
- return hr;
+ continue;
}
-
- /* Test for a specific Tuning space name supplied on the command
- * line as dvb-networkname=xxx */
- delete[] l.psz_bstr_name;
+ //msg_Dbg( p_access, "SetUpTuner: convert w to multi" );
+ if ( l.psz_bstr_name )
+ delete[] l.psz_bstr_name;
l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
l.psz_bstr_name, 0, NULL, NULL );
l.psz_bstr_name = new char[ l.i_name_len ];
l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
l.psz_bstr_name, l.i_name_len, NULL, NULL );
- if( *l.psz_network_name == '\0' ||
- strcmp( l.psz_network_name, l.psz_bstr_name ) == 0 )
- {
- msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %s",
- l.psz_bstr_name );
-
- /* CreateTuneRequest adds TuneRequest to p_tuning_space
- * p_tune_request->RefCount = 1 */
- hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
- if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Create Tune Request: hr=0x%8lx", hr );
- return hr;
- }
- if( p_tuning_space )
- p_tuning_space->Release();
- p_tuning_space = NULL;
+ msg_Dbg( p_access, "SetUpTuner: Using Tuning Space: %s",
+ l.psz_bstr_name );
+ break;
}
+
}
while( true );
+ //msg_Dbg( p_access, "SetUpTuner: checking what we got" );
- /* 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
- * network-name
- * Also would be nice to copy a tuning space but we only come here if we do
- * not find any. */
- l.psz_create_name = var_GetNonEmptyString( p_access, "dvb-create-name" );
- if( !l.psz_create_name || strlen( l.psz_create_name ) <= 0 )
- {
- hr = E_FAIL;
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot find a suitable System Tuning Space: hr=0x%8lx", hr );
- return hr;
+ if( l.guid_test_network_type == GUID_NULL)
+ {
+ msg_Dbg( p_access, "SetUpTuner: got null, try to clone" );
+ goto TryToClone;
}
- if( strcmp( l.psz_create_name, l.psz_network_name ) )
+
+ //msg_Dbg( p_access, "SetUpTuner: put TS" );
+ hr = p_scanning_tuner->put_TuningSpace( l.p_test_tuning_space );
+ if( FAILED( hr ) )
{
- hr = E_FAIL;
- msg_Warn( p_access, "CreateTuneRequest: "\
- "dvb-create-name %s must match dvb-network-name %s",
- l.psz_create_name, l.psz_network_name );
- return hr;
+ msg_Dbg( p_access, "SetUpTuner: "\
+ "cannot put tuning space: hr=0x%8lx", hr );
+ goto TryToClone;
}
- /* Need to use DVBSTuningSpace for DVB-S and ATSCTuningSpace for ATSC */
- VARIANT var_id;
- CLSID cls_tuning_space;
-
- if( IsEqualCLSID( guid_network_type, CLSID_ATSCNetworkProvider ) )
- cls_tuning_space = CLSID_ATSCTuningSpace;
- if( IsEqualCLSID( guid_network_type, CLSID_DVBTNetworkProvider ) )
- cls_tuning_space = CLSID_DVBTuningSpace;
- if( IsEqualCLSID( guid_network_type, CLSID_DVBCNetworkProvider ) )
- cls_tuning_space = CLSID_DVBTuningSpace;
- if( IsEqualCLSID( guid_network_type, CLSID_DVBSNetworkProvider ) )
- cls_tuning_space = CLSID_DVBSTuningSpace;
-
- l.i_name_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
- l.psz_create_name, -1, l.wpsz_create_name, 0 );
- if( l.i_name_len <= 0 )
+ //msg_Dbg( p_access, "SetUpTuner: get default locator" );
+ hr = l.p_test_tuning_space->get_DefaultLocator( &l.p_locator );
+ if( FAILED( hr ) )
{
- hr = E_FAIL;
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot convert zero length dvb-create-name %s",
- l.psz_create_name );
- return hr;
+ msg_Dbg( p_access, "SetUpTuner: "\
+ "cannot get default locator: hr=0x%8lx", hr );
+ goto TryToClone;
}
- l.wpsz_create_name = new WCHAR[l.i_name_len];
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, l.psz_create_name, -1,
- l.wpsz_create_name, l.i_name_len );
- if( l.bstr_name )
- SysFreeString( l.bstr_name );
- l.bstr_name = SysAllocString( l.wpsz_create_name );
-
- msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %s",
- l.psz_create_name );
-
- hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC,
- IID_ITuningSpace, (void**)&p_tuning_space );
+ //msg_Dbg( p_access, "SetUpTuner: create tune request" );
+ hr = l.p_test_tuning_space->CreateTuneRequest( &l.p_tune_request );
if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot CoCreate new TuningSpace: hr=0x%8lx", hr );
- if( SUCCEEDED( hr ) )
- hr = p_tuning_space->put__NetworkType( guid_network_type );
- if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Put Network Type: hr=0x%8lx", hr );
- if( SUCCEEDED( hr ) )
- hr = p_tuning_space->put_UniqueName( l.bstr_name );
- if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Put Unique Name: hr=0x%8lx", hr );
- if( SUCCEEDED( hr ) )
- hr = p_tuning_space->put_FriendlyName( l.bstr_name );
+ {
+ msg_Dbg( p_access, "SetUpTuner: "\
+ "cannot create tune request: hr=0x%8lx", hr );
+ goto TryToClone;
+ }
+
+ //msg_Dbg( p_access, "SetUpTuner: put locator" );
+ hr = l.p_tune_request->put_Locator( l.p_locator );
if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Put Friendly Name: hr=0x%8lx", hr );
- if( guid_network_type == CLSID_DVBTNetworkProvider ||
- guid_network_type == CLSID_DVBCNetworkProvider ||
- guid_network_type == CLSID_DVBSNetworkProvider )
{
- hr = p_tuning_space->QueryInterface( IID_IDVBTuningSpace2,
- (void**)&l.p_dvb_tuning_space );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot QI for IDVBTuningSpace2: hr=0x%8lx", hr );
- return hr;
- }
- if( guid_network_type == CLSID_DVBTNetworkProvider )
- hr = l.p_dvb_tuning_space->put_SystemType( DVB_Terrestrial );
- if( guid_network_type == CLSID_DVBCNetworkProvider )
- hr = l.p_dvb_tuning_space->put_SystemType( DVB_Cable );
- if( guid_network_type == CLSID_DVBSNetworkProvider )
- hr = l.p_dvb_tuning_space->put_SystemType( DVB_Satellite );
+ msg_Dbg( p_access, "SetUpTuner: "\
+ "cannot put locator: hr=0x%8lx", hr );
+ goto TryToClone;
}
- if( SUCCEEDED( hr ) )
- hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id );
+ //msg_Dbg( p_access, "SetUpTuner: try to validate tune request" );
+ hr = p_scanning_tuner->Validate( l.p_tune_request );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "SetUpTuner: "\
+ "Tune Request cannot be validated: hr=0x%8lx", hr );
+ }
+ //msg_Dbg( p_access, "SetUpTuner: Attach tune request to Scanning Tuner");
+ /* increments ref count for scanning tuner */
+ hr = p_scanning_tuner->put_TuneRequest( l.p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Create new TuningSpace: hr=0x%8lx", hr );
+ msg_Warn( p_access, "SetUpTuner: "\
+ "Cannot submit the tune request: hr=0x%8lx", hr );
return hr;
}
- msg_Dbg( p_access, "CreateTuneRequest: Tuning Space: %s created",
- l.psz_create_name );
+ //msg_Dbg( p_access, "SetUpTuner: Tuning Space: created" );
+ return S_OK;
- hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
- if( FAILED( hr ) )
- msg_Warn( p_access, "CreateTuneRequest: "\
- "Cannot Create Tune Request: hr=0x%8lx", hr );
+ /* Get the SystemTuningSpaces container
+ * p_tuning_space_container->Refcount = 1 */
+TryToClone:
+ msg_Warn( p_access, "SetUpTuner: won't try to clone " );
+ return E_FAIL;
+}
+/*****************************************************************************
+* GetNextNetworkType
+* helper function; this is probably best done as an Enumeration of
+* network providers
+*****************************************************************************/
+HRESULT BDAGraph::GetNextNetworkType( CLSID* guid_this_network_type )
+{
+ HRESULT hr = S_OK;
+ if( *guid_this_network_type == GUID_NULL )
+ {
+ msg_Dbg( p_access, "GetNextNetworkType: DVB-C" );
+ *guid_this_network_type = CLSID_DVBCNetworkProvider;
+ return S_OK;
+ }
+ if( *guid_this_network_type == CLSID_DVBCNetworkProvider )
+ {
+ msg_Dbg( p_access, "GetNextNetworkType: DVB-T" );
+ *guid_this_network_type = CLSID_DVBTNetworkProvider;
+ return S_OK;
+ }
+ if( *guid_this_network_type == CLSID_DVBTNetworkProvider )
+ {
+ msg_Dbg( p_access, "GetNextNetworkType: DVB-S" );
+ *guid_this_network_type = CLSID_DVBSNetworkProvider;
+ return S_OK;
+ }
+ if( *guid_this_network_type == CLSID_DVBSNetworkProvider )
+ {
+ msg_Dbg( p_access, "GetNextNetworkType: ATSC" );
+ *guid_this_network_type = CLSID_ATSCNetworkProvider;
+ return S_OK;
+ }
+ msg_Dbg( p_access, "GetNextNetworkType: failed" );
+ *guid_this_network_type = GUID_NULL;
+ hr = E_FAIL;
return hr;
}
+
/******************************************************************************
-* Build
-* Step 4: Build the Filter Graph
-* Build sets up devices, adds and connects filters
+* Check
+*******************************************************************************
+* Check if tuner supports this network type
+*
+* on success, sets globals:
+* systems, l_tuner_used, p_network_provider, p_scanning_tuner, p_tuner_device,
+* p_tuning_space, p_filter_graph
******************************************************************************/
-HRESULT BDAGraph::Build()
+HRESULT BDAGraph::Check( REFCLSID guid_this_network_type )
{
HRESULT hr = S_OK;
- long l_capture_used, l_tif_used;
- VARIANT l_tuning_space_id;
- AM_MEDIA_TYPE grabber_media_type;
+
class localComPtr
{
public:
ITuningSpaceContainer* p_tuning_space_container;
- localComPtr(): p_tuning_space_container(NULL) {};
+
+ localComPtr():
+ p_tuning_space_container(NULL)
+ {};
~localComPtr()
{
if( p_tuning_space_container )
@@ -1261,141 +1653,202 @@ HRESULT BDAGraph::Build()
}
} l;
- /* Get the SystemTuningSpaces container to save the Tuning space */
- l_tuning_space_id.vt = VT_I4;
- l_tuning_space_id.lVal = 0L;
- hr = ::CoCreateInstance( CLSID_SystemTuningSpaces, 0, CLSCTX_INPROC,
- IID_ITuningSpaceContainer, (void**)&l.p_tuning_space_container );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "Build: "\
- "Cannot CoCreate SystemTuningSpaces: hr=0x%8lx", hr );
- return hr;
- }
- hr = l.p_tuning_space_container->FindID( p_tuning_space,
- &l_tuning_space_id.lVal );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "Build: "\
- "Cannot Find Tuning Space ID: hr=0x%8lx", hr );
- return hr;
- }
- msg_Dbg( p_access, "Build: Using Tuning Space ID %ld",
- l_tuning_space_id.lVal );
- hr = l.p_tuning_space_container->put_Item( l_tuning_space_id,
- p_tuning_space );
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "Build: "\
- "Cannot save Tuning Space: hr=0x%8lx (ignored)", hr );
- }
+ msg_Dbg( p_access, "Check: entering 2012-03-14 ");
- /* If we have already have a filter graph, rebuild it*/
- Destroy();
+ /* Note that the systems global is persistent across Destroy().
+ * So we need to see if a tuner has been physically removed from
+ * the system since the last Check. Before we do anything,
+ * assume that this Check will fail and remove this network type
+ * from systems. It will be restored if the Check passes.
+ */
+
+ systems &= ~( GetSystem( guid_this_network_type ) );
+
+ /* If we have already have a filter graph, rebuild it*/
+ //msg_Dbg( p_access, "Check: Destroying filter graph" );
+ if( p_filter_graph )
+ Destroy();
+ p_filter_graph = NULL;
hr = ::CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC,
- IID_IGraphBuilder, (void**)&p_filter_graph );
+ IID_IGraphBuilder, reinterpret_cast<void**>( &p_filter_graph ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
+ msg_Warn( p_access, "Check: "\
"Cannot CoCreate IFilterGraph: hr=0x%8lx", hr );
return hr;
}
/* First filter in the graph is the Network Provider and
- * its Scanning Tuner which takes the Tune Request
- * Try to build the Win 7 Universal Network Provider first*/
- hr = ::CoCreateInstance( CLSID_NetworkProvider, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**)&p_network_provider);
+ * its Scanning Tuner which takes the Tune Request */
+ if( p_network_provider )
+ p_network_provider->Release();
+ p_network_provider = NULL;
+ hr = ::CoCreateInstance( guid_this_network_type, NULL, CLSCTX_INPROC_SERVER,
+ IID_IBaseFilter, reinterpret_cast<void**>( &p_network_provider ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
- "Cannot CoCreate the Universal Network Provider, trying the old way...");
- hr = ::CoCreateInstance( guid_network_type, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**)&p_network_provider);
- if( FAILED( hr ) )
- {
- msg_Warn( p_access, "Build: "\
- "Cannot CoCreate Network Provider: hr=0x%8lx", hr );
- return hr;
- }
+ msg_Warn( p_access, "Check: "\
+ "Cannot CoCreate Network Provider: hr=0x%8lx", hr );
+ return hr;
}
+
+ //msg_Dbg( p_access, "Check: adding Network Provider to graph");
hr = p_filter_graph->AddFilter( p_network_provider, L"Network Provider" );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
+ msg_Warn( p_access, "Check: "\
"Cannot load network provider: hr=0x%8lx", hr );
return hr;
}
/* 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. */
+ * Note that dvb-adapter is 1-based, while l_tuner_used is 0-based.
+ * 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;
+ /* If tuner is in cold state, we have to do a successful put_TuneRequest
+ * before it will Connect. */
+ //msg_Dbg( p_access, "Check: Creating Scanning Tuner");
+ if( p_scanning_tuner )
+ p_scanning_tuner->Release();
+ p_scanning_tuner = NULL;
+ hr = p_network_provider->QueryInterface( IID_IScanningTuner,
+ reinterpret_cast<void**>( &p_scanning_tuner ) );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Check: "\
+ "Cannot QI Network Provider for Scanning Tuner: hr=0x%8lx", hr );
+ return hr;
+ }
+
+ /* try to set up p_scanning_tuner */
+ //msg_Dbg( p_access, "Check: Calling SetUpTuner" );
+ hr = SetUpTuner( guid_this_network_type );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Check: "\
+ "Cannot set up scanner in Check mode: hr=0x%8lx", hr );
+ return hr;
+ }
+
+ msg_Dbg( p_access, "Check: "\
+ "Calling FindFilter for KSCATEGORY_BDA_NETWORK_TUNER with "\
+ "p_network_provider; l_tuner_used=%ld", l_tuner_used );
hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used,
p_network_provider, &p_tuner_device );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
+ msg_Warn( p_access, "Check: "\
"Cannot load tuner device and connect network provider: "\
"hr=0x%8lx", hr );
return hr;
}
+
if( l_adapter > 0 && l_tuner_used != l_adapter )
{
- msg_Warn( p_access, "Build: "\
+ msg_Warn( p_access, "Check: "\
"Tuner device %ld is not available", l_adapter );
- return E_FAIL;
+ return E_FAIL;
}
- msg_Dbg( p_access, "BDAGraph: Using adapter %ld", l_tuner_used );
-/* VLC 1.0 works reliably up this point then crashes
- * Obvious candidate is FindFilter */
- /* Always look for all capture devices to match the Network Tuner */
- l_capture_used = -1;
- hr = FindFilter( KSCATEGORY_BDA_RECEIVER_COMPONENT, &l_capture_used,
- p_tuner_device, &p_capture_device );
- if( FAILED( hr ) )
+ //msg_Dbg( p_access, "Check: Using adapter %ld", l_tuner_used );
+ /* success!
+ * already set l_tuner_used,
+ * p_tuning_space
+ */
+ //msg_Dbg( p_access, "Check: check succeeded: hr=0x%8lx", hr );
+ systems |= GetSystem( guid_this_network_type );
+ msg_Dbg( p_access, "Check: returning from Check mode" );
+ return S_OK;
+}
+
+
+/******************************************************************************
+* Build
+*******************************************************************************
+* Build the Filter Graph
+*
+* connects filters and
+* creates the media control and registers the graph
+* on success, sets globals:
+* d_graph_register, p_media_control, p_grabber, p_sample_grabber,
+* p_mpeg_demux, p_transport_info
+******************************************************************************/
+HRESULT BDAGraph::Build()
+{
+ HRESULT hr = S_OK;
+ long l_capture_used;
+ long l_tif_used;
+ AM_MEDIA_TYPE grabber_media_type;
+
+ class localComPtr
+ {
+ public:
+ ITuningSpaceContainer* p_tuning_space_container;
+ localComPtr():
+ p_tuning_space_container(NULL)
+ {};
+ ~localComPtr()
+ {
+ if( p_tuning_space_container )
+ p_tuning_space_container->Release();
+ }
+ } l;
+
+ msg_Dbg( p_access, "Build: entering 2012-03-04 ");
+
+ /* at this point, you've connected to a scanning tuner of the right
+ * network type.
+ */
+ if( !p_scanning_tuner || !p_tuner_device )
{
- /* Some BDA drivers do not provide a Capture Device Filter so force
- * the Sample Grabber to connect directly to the Tuner Device */
- p_capture_device = p_tuner_device;
- p_tuner_device = NULL;
msg_Warn( p_access, "Build: "\
- "Cannot find Capture device. Connecting to tuner: hr=0x%8lx", hr );
+ "Scanning Tuner does not exist" );
+ return E_FAIL;
}
- hr = p_network_provider->QueryInterface( IID_IScanningTuner,
- (void**)&p_scanning_tuner );
+ hr = p_scanning_tuner->get_TuneRequest( &p_tune_request );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
- "Cannot QI Network Provider for Scanning Tuner: hr=0x%8lx", hr );
+ msg_Warn( p_access, "Build: no tune request" );
return hr;
}
-
- hr = p_scanning_tuner->Validate( p_tune_request );
+ hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
- "Tune Request is invalid: hr=0x%8lx", hr );
- //return hr; it is not mandatory to validate. Validate fails, but the request is successfully accepted
+ msg_Warn( p_access, "Build: no tuning space" );
+ return hr;
}
- hr = p_scanning_tuner->put_TuneRequest( p_tune_request );
+ hr = p_tuning_space->get__NetworkType( &guid_network_type );
+
+
+ /* Always look for all capture devices to match the Network Tuner */
+ l_capture_used = -1;
+ msg_Dbg( p_access, "Build: "\
+ "Calling FindFilter for KSCATEGORY_BDA_RECEIVER_COMPONENT with "\
+ "p_tuner_device; l_capture_used=%ld", l_capture_used );
+ hr = FindFilter( KSCATEGORY_BDA_RECEIVER_COMPONENT, &l_capture_used,
+ p_tuner_device, &p_capture_device );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "Build: "\
- "Cannot submit the tune request: hr=0x%8lx", hr );
- return hr;
+ /* Some BDA drivers do not provide a Capture Device Filter so force
+ * the Sample Grabber to connect directly to the Tuner Device */
+ msg_Dbg( p_access, "Build: "\
+ "Cannot find Capture device. Connect to tuner "\
+ "and AddRef() : hr=0x%8lx", hr );
+ p_capture_device = p_tuner_device;
+ p_capture_device->AddRef();
}
if( p_sample_grabber )
@@ -1403,13 +1856,14 @@ HRESULT BDAGraph::Build()
p_sample_grabber = NULL;
/* Insert the Sample Grabber to tap into the Transport Stream. */
hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
- IID_IBaseFilter, (void**)&p_sample_grabber );
+ IID_IBaseFilter, reinterpret_cast<void**>( &p_sample_grabber ) );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Build: "\
"Cannot load Sample Grabber Filter: hr=0x%8lx", hr );
return hr;
}
+
hr = p_filter_graph->AddFilter( p_sample_grabber, L"Sample Grabber" );
if( FAILED( hr ) )
{
@@ -1418,11 +1872,12 @@ HRESULT BDAGraph::Build()
return hr;
}
+ /* create the sample grabber */
if( p_grabber )
p_grabber->Release();
p_grabber = NULL;
hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber,
- (void**)&p_grabber );
+ reinterpret_cast<void**>( &p_grabber ) );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Build: "\
@@ -1445,7 +1900,11 @@ HRESULT BDAGraph::Build()
{
hr = Connect( p_capture_device, p_sample_grabber );
if( SUCCEEDED( hr ) )
+ {
+ msg_Dbg( p_access, "Build: "\
+ "Connected capture device to sample grabber" );
break;
+ }
msg_Warn( p_access, "Build: "\
"Cannot connect Sample Grabber to Capture device: hr=0x%8lx (try %d/2)", hr, 1+i );
}
@@ -1455,20 +1914,32 @@ HRESULT BDAGraph::Build()
"Cannot set media type on grabber filter: hr=0x%8lx (try %d/2", hr, 1+i );
}
}
- if( hr )
+ msg_Dbg( p_access, "Build: This is where it used to return upon success" );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Build: "\
+ "Cannot use capture device: hr=0x%8lx", hr );
return hr;
+ }
/* We need the MPEG2 Demultiplexer even though we are going to use the VLC
* TS demuxer. The TIF filter connects to the MPEG2 demux and works with
* the Network Provider filter to set up the stream */
+ //msg_Dbg( p_access, "Build: using MPEG2 demux" );
+ if( p_mpeg_demux )
+ p_mpeg_demux->Release();
+ p_mpeg_demux = NULL;
hr = ::CoCreateInstance( CLSID_MPEG2Demultiplexer, NULL,
- CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&p_mpeg_demux );
+ CLSCTX_INPROC_SERVER, IID_IBaseFilter,
+ reinterpret_cast<void**>( &p_mpeg_demux ) );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Build: "\
"Cannot CoCreateInstance MPEG2 Demultiplexer: hr=0x%8lx", hr );
return hr;
}
+
+ //msg_Dbg( p_access, "Build: adding demux" );
hr = p_filter_graph->AddFilter( p_mpeg_demux, L"Demux" );
if( FAILED( hr ) )
{
@@ -1476,6 +1947,7 @@ HRESULT BDAGraph::Build()
"Cannot add demux filter to graph: hr=0x%8lx", hr );
return hr;
}
+
hr = Connect( p_sample_grabber, p_mpeg_demux );
if( FAILED( hr ) )
{
@@ -1484,9 +1956,15 @@ HRESULT BDAGraph::Build()
return hr;
}
- /* Always look for the Transform Information Filter from the start
+ //msg_Dbg( p_access, "Build: Connected sample grabber to demux" );
+ /* Always look for the Transport Information Filter from the start
* of the collection*/
l_tif_used = -1;
+ msg_Dbg( p_access, "Check: "\
+ "Calling FindFilter for KSCATEGORY_BDA_TRANSPORT_INFORMATION with "\
+ "p_mpeg_demux; l_tif_used=%ld", l_tif_used );
+
+
hr = FindFilter( KSCATEGORY_BDA_TRANSPORT_INFORMATION, &l_tif_used,
p_mpeg_demux, &p_transport_info );
if( FAILED( hr ) )
@@ -1495,6 +1973,7 @@ HRESULT BDAGraph::Build()
"Cannot load TIF onto demux: hr=0x%8lx", hr );
return hr;
}
+
/* Configure the Sample Grabber to buffer the samples continuously */
hr = p_grabber->SetBufferSamples( true );
if( FAILED( hr ) )
@@ -1503,6 +1982,7 @@ HRESULT BDAGraph::Build()
"Cannot set Sample Grabber to buffering: hr=0x%8lx", hr );
return hr;
}
+
hr = p_grabber->SetOneShot( false );
if( FAILED( hr ) )
{
@@ -1510,6 +1990,11 @@ HRESULT BDAGraph::Build()
"Cannot set Sample Grabber to multi shot: hr=0x%8lx", hr );
return hr;
}
+
+ /* Second parameter to SetCallback specifies the callback method; 0 uses
+ * the ISampleGrabberCB::SampleCB method, which receives an IMediaSample
+ * pointer. */
+ //msg_Dbg( p_access, "Build: Adding grabber callback" );
hr = p_grabber->SetCallback( this, 0 );
if( FAILED( hr ) )
{
@@ -1518,10 +2003,12 @@ HRESULT BDAGraph::Build()
return hr;
}
- hr = Register();
+ hr = Register(); /* creates d_graph_register */
if( FAILED( hr ) )
{
d_graph_register = 0;
+ msg_Dbg( p_access, "Build: "\
+ "Cannot register graph: hr=0x%8lx", hr );
}
/* The Media Control is used to Run and Stop the Graph */
@@ -1529,7 +2016,7 @@ HRESULT BDAGraph::Build()
p_media_control->Release();
p_media_control = NULL;
hr = p_filter_graph->QueryInterface( IID_IMediaControl,
- (void**)&p_media_control );
+ reinterpret_cast<void**>( &p_media_control ) );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Build: "\
@@ -1537,8 +2024,184 @@ HRESULT BDAGraph::Build()
return hr;
}
- return hr;
+ /* success! */
+ //msg_Dbg( p_access, "Build: succeeded: hr=0x%8lx", hr );
+ return S_OK;
+}
+
+/* debugging */
+HRESULT BDAGraph::ListFilters( REFCLSID this_clsid )
+{
+ HRESULT hr = S_OK;
+
+ class localComPtr
+ {
+ public:
+ ICreateDevEnum* p_local_system_dev_enum;
+ IEnumMoniker* p_moniker_enum;
+ IMoniker* p_moniker;
+ IBaseFilter* p_filter;
+ IBaseFilter* p_this_filter;
+ IBindCtx* p_bind_context;
+ IPropertyBag* p_property_bag;
+
+ char* psz_downstream;
+ char* psz_bstr;
+ int i_bstr_len;
+
+ localComPtr():
+ p_local_system_dev_enum(NULL),
+ p_moniker_enum(NULL),
+ p_moniker(NULL),
+ p_filter(NULL),
+ p_this_filter(NULL),
+ p_bind_context( NULL ),
+ p_property_bag(NULL),
+ psz_downstream( NULL ),
+ psz_bstr( NULL )
+ {}
+ ~localComPtr()
+ {
+ if( p_property_bag )
+ p_property_bag->Release();
+ if( p_bind_context )
+ p_bind_context->Release();
+ if( p_filter )
+ p_filter->Release();
+ if( p_this_filter )
+ p_this_filter->Release();
+ if( p_moniker )
+ p_moniker->Release();
+ if( p_moniker_enum )
+ p_moniker_enum->Release();
+ if( p_local_system_dev_enum )
+ p_local_system_dev_enum->Release();
+ if( psz_bstr )
+ delete[] psz_bstr;
+ if( psz_downstream )
+ delete[] psz_downstream;
+ }
+ } l;
+
+
+// msg_Dbg( p_access, "ListFilters: Create local system_dev_enum 03-01");
+ if( l.p_local_system_dev_enum )
+ l.p_local_system_dev_enum->Release();
+ l.p_local_system_dev_enum = NULL;
+ hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
+ IID_ICreateDevEnum, reinterpret_cast<void**>( &l.p_local_system_dev_enum ) );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "ListFilters: "\
+ "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
+ return hr;
+ }
+
+ //msg_Dbg( p_access, "ListFilters: Create p_moniker_enum");
+ if( l.p_moniker_enum )
+ l.p_moniker_enum->Release();
+ l.p_moniker_enum = NULL;
+ hr = l.p_local_system_dev_enum->CreateClassEnumerator( this_clsid,
+ &l.p_moniker_enum, 0 );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "ListFilters: "\
+ "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
+ return hr;
+ }
+
+ //msg_Dbg( p_access, "ListFilters: Entering main loop" );
+ 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 */
+ /* msg_Dbg( p_access, "ListFilters: top of main loop");*/
+ //msg_Dbg( p_access, "ListFilters: releasing property bag");
+ if( l.p_property_bag )
+ l.p_property_bag->Release();
+ l.p_property_bag = NULL;
+ //msg_Dbg( p_access, "ListFilters: releasing filter");
+ if( l.p_filter )
+ l.p_filter->Release();
+ l.p_filter = NULL;
+ //msg_Dbg( p_access, "ListFilters: releasing bind context");
+ if( l.p_bind_context )
+ l.p_bind_context->Release();
+ l.p_bind_context = NULL;
+ //msg_Dbg( p_access, "ListFilters: releasing moniker");
+ if( l.p_moniker )
+ l.p_moniker->Release();
+ l.p_moniker = NULL;
+ //msg_Dbg( p_access, "ListFilters: trying a moniker");
+
+ if( !l.p_moniker_enum ) break;
+ hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
+ if( hr != S_OK ) break;
+
+ /* l.p_bind_context is Released at the top of the loop */
+ hr = CreateBindCtx( 0, &l.p_bind_context );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "ListFilters: "\
+ "Cannot create bind_context, trying another: hr=0x%8lx", hr );
+ continue;
+ }
+
+ /* l.p_filter is Released at the top of the loop */
+ hr = l.p_moniker->BindToObject( l.p_bind_context, NULL, IID_IBaseFilter,
+ reinterpret_cast<void**>( &l.p_filter ) );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "ListFilters: "\
+ "Cannot create p_filter, trying another: hr=0x%8lx", hr );
+ continue;
+ }
+
+#ifdef DEBUG_MONIKER_NAME
+ WCHAR* pwsz_downstream = NULL;
+
+ hr = l.p_moniker->GetDisplayName(l.p_bind_context, NULL,
+ &pwsz_downstream );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "ListFilters: "\
+ "Cannot get display name, trying another: hr=0x%8lx", hr );
+ continue;
+ }
+ if( l.psz_downstream )
+ delete[] l.psz_downstream;
+ l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
+ l.psz_downstream, 0, NULL, NULL );
+ l.psz_downstream = new char[ l.i_bstr_len ];
+ l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
+ l.psz_downstream, l.i_bstr_len, NULL, NULL );
+
+ LPMALLOC p_alloc;
+ ::CoGetMalloc( 1, &p_alloc );
+ p_alloc->Free( pwsz_downstream );
+ p_alloc->Release();
+ msg_Dbg( p_access, "ListFilters: "\
+ "Moniker name is %s", l.psz_downstream );
+#else
+ l.psz_downstream = strdup( "Downstream" );
+#endif
+ /* l.p_property_bag is released at the top of the loop */
+ hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
+ reinterpret_cast<void**>( &l.p_property_bag ) );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "ListFilters: "\
+ "Cannot Bind to Property Bag: hr=0x%8lx", hr );
+ continue;
+ }
+
+ //msg_Dbg( p_access, "ListFilters: displaying another" );
+ }
+ while( true );
+
+ return S_OK;
}
/******************************************************************************
@@ -1550,7 +2213,7 @@ HRESULT BDAGraph::Build()
* This is used when the graph does not run because a tuner device is in use so
* another one needs to be selected.
******************************************************************************/
-HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
+HRESULT BDAGraph::FindFilter( REFCLSID this_clsid, long* i_moniker_used,
IBaseFilter* p_upstream, IBaseFilter** p_p_downstream )
{
HRESULT hr = S_OK;
@@ -1558,39 +2221,52 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
class localComPtr
{
public:
- IMoniker* p_moniker;
IEnumMoniker* p_moniker_enum;
- IBaseFilter* p_filter;
+ IMoniker* p_moniker;
+ IBindCtx* p_bind_context;
IPropertyBag* p_property_bag;
+ char* psz_upstream;
+ int i_upstream_len;
+
+ char* psz_downstream;
VARIANT var_bstr;
- char * psz_bstr;
int i_bstr_len;
localComPtr():
- p_moniker(NULL),
p_moniker_enum(NULL),
- p_filter(NULL),
+ p_moniker(NULL),
+ p_bind_context( NULL ),
p_property_bag(NULL),
- psz_bstr( NULL )
- { ::VariantInit(&var_bstr); };
+ psz_upstream( NULL ),
+ psz_downstream( NULL )
+ {
+ ::VariantInit(&var_bstr);
+ }
~localComPtr()
{
- if( p_property_bag )
- p_property_bag->Release();
- if( p_filter )
- p_filter->Release();
- if( p_moniker )
- p_moniker->Release();
if( p_moniker_enum )
p_moniker_enum->Release();
+ if( p_moniker )
+ p_moniker->Release();
+ if( p_bind_context )
+ p_bind_context->Release();
+ if( p_property_bag )
+ p_property_bag->Release();
+ if( psz_upstream )
+ delete[] psz_upstream;
+ if( psz_downstream )
+ delete[] psz_downstream;
+
::VariantClear(&var_bstr);
- delete[] psz_bstr;
}
} l;
+ /* create system_dev_enum the first time through, or preserve the
+ * existing one to loop through classes */
if( !p_system_dev_enum )
{
+ //msg_Dbg( p_access, "FindFilter: Create p_system_dev_enum");
hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
- IID_ICreateDevEnum, (void**)&p_system_dev_enum );
+ IID_ICreateDevEnum, reinterpret_cast<void**>( &p_system_dev_enum ) );
if( FAILED( hr ) )
{
msg_Warn( p_access, "FindFilter: "\
@@ -1599,98 +2275,169 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
}
}
- hr = p_system_dev_enum->CreateClassEnumerator( clsid,
+ //msg_Dbg( p_access, "FindFilter: Create p_moniker_enum");
+ hr = p_system_dev_enum->CreateClassEnumerator( this_clsid,
&l.p_moniker_enum, 0 );
- if( hr != S_OK )
+ if( FAILED( hr ) )
{
msg_Warn( p_access, "FindFilter: "\
"Cannot CreateClassEnumerator: hr=0x%8lx", hr );
- return E_FAIL;
+ return hr;
+ }
+
+ //msg_Dbg( p_access, "FindFilter: get filter name");
+ hr = GetFilterName( p_upstream, &l.psz_upstream );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "FindFilter: "\
+ "Cannot GetFilterName: hr=0x%8lx", hr );
+ return hr;
}
+ msg_Dbg( p_access, "FindFilter: "\
+ "called with i_moniker_used=%ld, " \
+ "p_upstream = %s", *i_moniker_used, l.psz_upstream );
+
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 */
+ * It is important that p_moniker and p_property_bag are fully released */
+ //msg_Dbg( p_access, "FindFilter: top of main loop");
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;
+ //msg_Dbg( p_access, "FindFilter: releasing bind context");
+ if( l.p_bind_context )
+ l.p_bind_context->Release();
+ l.p_bind_context = NULL;
+ //msg_Dbg( p_access, "FindFilter: releasing moniker");
if( l.p_moniker )
l.p_moniker->Release();
- l.p_moniker = NULL;
+ //msg_Dbg( p_access, "FindFilter: null moniker");
+ l.p_moniker = NULL;
+ //msg_Dbg( p_access, "FindFilter: quit if no enum");
+ if( !l.p_moniker_enum ) break;
+ //msg_Dbg( p_access, "FindFilter: trying a moniker");
hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
if( hr != S_OK ) break;
+
i_moniker_index++;
/* Skip over devices already found on previous calls */
+ //msg_Dbg( p_access, "FindFilter: skip previously found devices");
+
if( i_moniker_index <= *i_moniker_used ) continue;
*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,
- (void**)&l.p_filter );
+ /* l.p_bind_context is Released at the top of the loop */
+ //msg_Dbg( p_access, "FindFilter: create bind context");
+ hr = CreateBindCtx( 0, &l.p_bind_context );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "FindFilter: "\
+ "Cannot create bind_context, trying another: hr=0x%8lx", hr );
+ continue;
+ }
+
+ //msg_Dbg( p_access, "FindFilter: try to create downstream filter");
+ *p_p_downstream = NULL;
+ hr = l.p_moniker->BindToObject( l.p_bind_context, NULL, IID_IBaseFilter,
+ reinterpret_cast<void**>( p_p_downstream ) );
if( FAILED( hr ) )
{
+ msg_Dbg( p_access, "FindFilter: "\
+ "Cannot bind to downstream, trying another: hr=0x%8lx", hr );
continue;
}
+
+#ifdef DEBUG_MONIKER_NAME
+ msg_Dbg( p_access, "FindFilter: get downstream filter name");
+
+ WCHAR* pwsz_downstream = NULL;
+
+ hr = l.p_moniker->GetDisplayName(l.p_bind_context, NULL,
+ &pwsz_downstream );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "FindFilter: "\
+ "Cannot get display name, trying another: hr=0x%8lx", hr );
+ continue;
+ }
+
+ if( l.psz_downstream )
+ delete[] l.psz_downstream;
+ l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
+ l.psz_downstream, 0, NULL, NULL );
+ l.psz_downstream = new char[ l.i_bstr_len ];
+ l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
+ l.psz_downstream, l.i_bstr_len, NULL, NULL );
+
+ LPMALLOC p_alloc;
+ ::CoGetMalloc( 1, &p_alloc );
+ p_alloc->Free( pwsz_downstream );
+ p_alloc->Release();
+#else
+ l.psz_downstream = strdup( "Downstream" );
+#endif
+
/* l.p_property_bag is released at the top of the loop */
- hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
- (void**)&l.p_property_bag );
+ msg_Dbg( p_access, "FindFilter: "\
+ "Moniker name is %s, binding to storage", l.psz_downstream );
+ hr = l.p_moniker->BindToStorage( l.p_bind_context, NULL,
+ IID_IPropertyBag, reinterpret_cast<void**>( &l.p_property_bag ) );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "FindFilter: "\
+ msg_Dbg( p_access, "FindFilter: "\
"Cannot Bind to Property Bag: hr=0x%8lx", hr );
- return hr;
+ continue;
}
+
+ //msg_Dbg( p_access, "FindFilter: read friendly name");
hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "FindFilter: "\
- "Cannot read filter friendly name: hr=0x%8lx", hr );
- return hr;
+ msg_Dbg( p_access, "FindFilter: "\
+ "Cannot read friendly name, next?: hr=0x%8lx", hr );
+ continue;
}
- hr = p_filter_graph->AddFilter( l.p_filter, l.var_bstr.bstrVal );
+ //msg_Dbg( p_access, "FindFilter: add filter to graph" );
+ hr = p_filter_graph->AddFilter( *p_p_downstream, l.var_bstr.bstrVal );
if( FAILED( hr ) )
{
- msg_Warn( p_access, "FindFilter: "\
- "Cannot add filter: hr=0x%8lx", hr );
- return hr;
+ msg_Dbg( p_access, "FindFilter: "\
+ "Cannot add filter, trying another: hr=0x%8lx", hr );
+ continue;
}
- hr = Connect( p_upstream, l.p_filter );
+
+ msg_Dbg( p_access, "FindFilter: "\
+ "Trying to Connect %s to %s", l.psz_upstream, l.psz_downstream );
+ hr = Connect( p_upstream, *p_p_downstream );
if( SUCCEEDED( hr ) )
{
- /* p_p_downstream has not been touched yet so no release needed */
- delete[] l.psz_bstr;
- l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0,
- l.var_bstr.bstrVal, -1, l.psz_bstr, 0, NULL, NULL );
- l.psz_bstr = new char[l.i_bstr_len];
- l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0,
- l.var_bstr.bstrVal, -1, l.psz_bstr, l.i_bstr_len, NULL, NULL );
- msg_Dbg( p_access, "FindFilter: Connected %s", l.psz_bstr );
- l.p_filter->QueryInterface( IID_IBaseFilter,
- (void**)p_p_downstream );
+ msg_Dbg( p_access, "FindFilter: Connected %s", l.psz_downstream );
return S_OK;
}
+
/* Not the filter we want so unload and try the next one */
- hr = p_filter_graph->RemoveFilter( l.p_filter );
+ /* Warning: RemoveFilter does an undocumented Release()
+ * on pointer but does not set it to NULL */
+ //msg_Dbg( p_access, "FindFilter: Removing filter" );
+ hr = p_filter_graph->RemoveFilter( *p_p_downstream );
if( FAILED( hr ) )
{
msg_Warn( p_access, "FindFilter: "\
"Failed unloading Filter: hr=0x%8lx", hr );
- return hr;
+ continue;
}
-
+ //msg_Dbg( p_access, "FindFilter: trying another" );
}
while( true );
+ /* nothing found */
+ msg_Warn( p_access, "FindFilter: No filter connected" );
hr = E_FAIL;
- msg_Warn( p_access, "FindFilter: No filter connected: hr=0x%8lx", hr );
return hr;
}
@@ -1708,9 +2455,16 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
IEnumPins* p_pin_upstream_enum;
IEnumPins* p_pin_downstream_enum;
IPin* p_pin_temp;
- localComPtr(): p_pin_upstream(NULL), p_pin_downstream(NULL),
+ char* psz_upstream;
+ char* psz_downstream;
+
+ localComPtr():
+ p_pin_upstream(NULL), p_pin_downstream(NULL),
p_pin_upstream_enum(NULL), p_pin_downstream_enum(NULL),
- p_pin_temp(NULL) { };
+ p_pin_temp(NULL),
+ psz_upstream( NULL ),
+ psz_downstream( NULL )
+ { };
~localComPtr()
{
if( p_pin_temp )
@@ -1723,11 +2477,16 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
p_pin_downstream_enum->Release();
if( p_pin_upstream_enum )
p_pin_upstream_enum->Release();
+ if( psz_upstream )
+ delete[] psz_upstream;
+ if( psz_downstream )
+ delete[] psz_downstream;
}
} l;
PIN_DIRECTION pin_dir;
+ //msg_Dbg( p_access, "Connect: entering" );
hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
if( FAILED( hr ) )
{
@@ -1739,12 +2498,23 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
do
{
/* Release l.p_pin_upstream before next iteration */
- if( l.p_pin_upstream )
+ if( l.p_pin_upstream )
l.p_pin_upstream ->Release();
l.p_pin_upstream = NULL;
+ if( !l.p_pin_upstream_enum ) break;
hr = l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 );
if( hr != S_OK ) break;
+ //msg_Dbg( p_access, "Connect: get pin name");
+ hr = GetPinName( l.p_pin_upstream, &l.psz_upstream );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Connect: "\
+ "Cannot GetPinName: hr=0x%8lx", hr );
+ return hr;
+ }
+ //msg_Dbg( p_access, "Connect: p_pin_upstream = %s", l.psz_upstream );
+
hr = l.p_pin_upstream->QueryDirection( &pin_dir );
if( FAILED( hr ) )
{
@@ -1752,22 +2522,26 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
"Cannot get upstream filter pin direction: hr=0x%8lx", hr );
return hr;
}
+
hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
if( SUCCEEDED( hr ) )
{
l.p_pin_downstream->Release();
l.p_pin_downstream = NULL;
}
+
if( FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
{
msg_Warn( p_access, "Connect: "\
"Cannot check upstream filter connection: hr=0x%8lx", hr );
return hr;
}
+
if( ( pin_dir == PINDIR_OUTPUT ) && ( hr == VFW_E_NOT_CONNECTED ) )
{
/* The upstream pin is not yet connected so check each pin on the
* downstream filter */
+ //msg_Dbg( p_access, "Connect: enumerating downstream pins" );
hr = p_downstream->EnumPins( &l.p_pin_downstream_enum );
if( FAILED( hr ) )
{
@@ -1775,16 +2549,30 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
"downstream filter enumerator: hr=0x%8lx", hr );
return hr;
}
+
do
{
/* Release l.p_pin_downstream before next iteration */
- if( l.p_pin_downstream )
+ if( l.p_pin_downstream )
l.p_pin_downstream ->Release();
l.p_pin_downstream = NULL;
-
+ if( !l.p_pin_downstream_enum ) break;
hr = l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 );
if( hr != S_OK ) break;
+ //msg_Dbg( p_access, "Connect: get pin name");
+ hr = GetPinName( l.p_pin_downstream, &l.psz_downstream );
+ if( FAILED( hr ) )
+ {
+ msg_Warn( p_access, "Connect: "\
+ "Cannot GetPinName: hr=0x%8lx", hr );
+ return hr;
+ }
+/*
+ msg_Dbg( p_access, "Connect: Trying p_downstream = %s",
+ l.psz_downstream );
+*/
+
hr = l.p_pin_downstream->QueryDirection( &pin_dir );
if( FAILED( hr ) )
{
@@ -1802,6 +2590,7 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
l.p_pin_temp->Release();
l.p_pin_temp = NULL;
}
+
if( hr != VFW_E_NOT_CONNECTED )
{
if( FAILED( hr ) )
@@ -1811,9 +2600,12 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
return hr;
}
}
+
if( ( pin_dir == PINDIR_INPUT ) &&
( hr == VFW_E_NOT_CONNECTED ) )
{
+ //msg_Dbg( p_access, "Connect: trying to connect pins" );
+
hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
l.p_pin_downstream, NULL );
if( SUCCEEDED( hr ) )
@@ -1844,6 +2636,7 @@ HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
while( true );
/* If we arrive here it means we did not find any pair of suitable pins
* Outstanding refcounts are released in the destructor */
+ //msg_Dbg( p_access, "Connect: No pins connected" );
return E_FAIL;
}
@@ -1855,18 +2648,25 @@ HRESULT BDAGraph::Start()
HRESULT hr = S_OK;
OAFilterState i_state; /* State_Stopped, State_Paused, State_Running */
+ msg_Dbg( p_access, "Start: entering" );
+
if( !p_media_control )
{
- msg_Dbg( p_access, "Start: Media Control has not been created" );
+ msg_Warn( p_access, "Start: Media Control has not been created" );
return E_FAIL;
}
+
+ msg_Dbg( p_access, "Start: Run()" );
hr = p_media_control->Run();
- msg_Dbg( p_access, "Graph started hr=0x%lx", hr );
- if( hr == S_OK )
- return hr;
+ if( SUCCEEDED( hr ) )
+ {
+ msg_Dbg( p_access, "Start: Graph started, hr=0x%lx", hr );
+ return S_OK;
+ }
+ msg_Dbg( p_access, "Start: would not start, will retry" );
/* Query the state of the graph - timeout after 100 milliseconds */
- while( (hr = p_media_control->GetState( 100, &i_state )) != S_OK )
+ while( (hr = p_media_control->GetState( 100, &i_state) ) != S_OK )
{
if( FAILED( hr ) )
{
@@ -1875,8 +2675,13 @@ HRESULT BDAGraph::Start()
return hr;
}
}
+
+ msg_Dbg( p_access, "Start: got state" );
if( i_state == State_Running )
- return hr;
+ {
+ msg_Dbg( p_access, "Graph started after a delay, hr=0x%lx", hr );
+ return S_OK;
+ }
/* The Graph is not running so stop it and return an error */
msg_Warn( p_access, "Start: Graph not started: %d", (int)i_state );
@@ -1887,6 +2692,7 @@ HRESULT BDAGraph::Start()
"Start: Cannot stop Graph after Run failed: hr=0x%8lx", hr );
return hr;
}
+
return E_FAIL;
}
@@ -1907,6 +2713,10 @@ STDMETHODIMP BDAGraph::SampleCB( double /*date*/, IMediaSample *p_sample )
msg_Warn( p_access, "BDA SampleCB: Sample Discontinuity.");
const size_t i_sample_size = p_sample->GetActualDataLength();
+
+ /* The buffer memory is owned by the media sample object, and is automatically
+ * released when the media sample is destroyed. The caller should not free or
+ * reallocate the buffer. */
BYTE *p_sample_data;
p_sample->GetPointer( &p_sample_data );
@@ -1934,80 +2744,166 @@ STDMETHODIMP BDAGraph::BufferCB( double /*date*/, BYTE* /*buffer*/,
******************************************************************************/
HRESULT BDAGraph::Destroy()
{
+ HRESULT hr = S_OK;
+ ULONG mem_ref = 0;
+// msg_Dbg( p_access, "Destroy: media control 1" );
if( p_media_control )
p_media_control->StopWhenReady(); /* Instead of Stop() */
+// msg_Dbg( p_access, "Destroy: deregistering graph" );
if( d_graph_register )
- {
Deregister();
- }
+// msg_Dbg( p_access, "Destroy: calling Empty" );
output.Empty();
- if( p_grabber )
- {
- p_grabber->Release();
- p_grabber = NULL;
- }
-
+// msg_Dbg( p_access, "Destroy: TIF" );
if( p_transport_info )
{
- p_filter_graph->RemoveFilter( p_transport_info );
- p_transport_info->Release();
+ /* Warning: RemoveFilter does an undocumented Release()
+ * on pointer but does not set it to NULL */
+ hr = p_filter_graph->RemoveFilter( p_transport_info );
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading TIF: hr=0x%8lx", hr );
+ }
p_transport_info = NULL;
}
+
+// msg_Dbg( p_access, "Destroy: demux" );
if( p_mpeg_demux )
{
p_filter_graph->RemoveFilter( p_mpeg_demux );
- p_mpeg_demux->Release();
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading demux: hr=0x%8lx", hr );
+ }
p_mpeg_demux = NULL;
}
+
+// msg_Dbg( p_access, "Destroy: sample grabber" );
+ if( p_grabber )
+ {
+ mem_ref = p_grabber->Release();
+ if( mem_ref != 0 )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Sample grabber mem_ref (varies): mem_ref=%ld", mem_ref );
+ }
+ p_grabber = NULL;
+ }
+
+// msg_Dbg( p_access, "Destroy: sample grabber filter" );
if( p_sample_grabber )
{
- p_filter_graph->RemoveFilter( p_sample_grabber );
- p_sample_grabber->Release();
+ hr = p_filter_graph->RemoveFilter( p_sample_grabber );
p_sample_grabber = NULL;
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading sampler: hr=0x%8lx", hr );
+ }
}
+
+// msg_Dbg( p_access, "Destroy: capture device" );
if( p_capture_device )
{
p_filter_graph->RemoveFilter( p_capture_device );
- p_capture_device->Release();
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading capture device: hr=0x%8lx", hr );
+ }
p_capture_device = NULL;
}
+
+// msg_Dbg( p_access, "Destroy: tuner device" );
if( p_tuner_device )
{
- p_filter_graph->RemoveFilter( p_tuner_device );
- p_tuner_device->Release();
+ //msg_Dbg( p_access, "Destroy: remove filter on tuner device" );
+ hr = p_filter_graph->RemoveFilter( p_tuner_device );
+ //msg_Dbg( p_access, "Destroy: force tuner device to NULL" );
p_tuner_device = NULL;
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading tuner device: hr=0x%8lx", hr );
+ }
}
+
+// msg_Dbg( p_access, "Destroy: scanning tuner" );
if( p_scanning_tuner )
{
- p_scanning_tuner->Release();
+ mem_ref = p_scanning_tuner->Release();
+ if( mem_ref != 0 )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Scanning tuner mem_ref (normally 2 if warm, "\
+ "3 if active): mem_ref=%ld", mem_ref );
+ }
p_scanning_tuner = NULL;
}
+
+// msg_Dbg( p_access, "Destroy: net provider" );
if( p_network_provider )
{
- p_filter_graph->RemoveFilter( p_network_provider );
- p_network_provider->Release();
+ hr = p_filter_graph->RemoveFilter( p_network_provider );
p_network_provider = NULL;
+ if( FAILED( hr ) )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Failed unloading net provider: hr=0x%8lx", hr );
+ }
}
- if( p_media_control )
- {
- p_media_control->Release();
- p_media_control = NULL;
- }
+// msg_Dbg( p_access, "Destroy: filter graph" );
if( p_filter_graph )
{
- p_filter_graph->Release();
+ mem_ref = p_filter_graph->Release();
+ if( mem_ref != 0 )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Filter graph mem_ref (normally 1 if active): mem_ref=%ld",
+ mem_ref );
+ }
p_filter_graph = NULL;
}
+
+ /* first call to FindFilter creates p_system_dev_enum */
+
+// msg_Dbg( p_access, "Destroy: system dev enum" );
if( p_system_dev_enum )
{
- p_system_dev_enum->Release();
+ mem_ref = p_system_dev_enum->Release();
+ if( mem_ref != 0 )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "System_dev_enum mem_ref: mem_ref=%ld", mem_ref );
+ }
p_system_dev_enum = NULL;
}
+// msg_Dbg( p_access, "Destroy: media control 2" );
+ if( p_media_control )
+ {
+ msg_Dbg( p_access, "Destroy: release media control" );
+ mem_ref = p_media_control->Release();
+ if( mem_ref != 0 )
+ {
+ msg_Dbg( p_access, "Destroy: "\
+ "Media control mem_ref: mem_ref=%ld", mem_ref );
+ }
+ msg_Dbg( p_access, "Destroy: force media control to NULL" );
+ p_media_control = NULL;
+ }
+
+ d_graph_register = 0;
+ l_tuner_used = -1;
+ guid_network_type = GUID_NULL;
+
+// msg_Dbg( p_access, "Destroy: returning" );
return S_OK;
}
@@ -2022,7 +2918,10 @@ HRESULT BDAGraph::Register()
public:
IMoniker* p_moniker;
IRunningObjectTable* p_ro_table;
- localComPtr(): p_moniker(NULL), p_ro_table(NULL) {};
+ localComPtr():
+ p_moniker(NULL),
+ p_ro_table(NULL)
+ {};
~localComPtr()
{
if( p_moniker )
@@ -2031,7 +2930,7 @@ HRESULT BDAGraph::Register()
p_ro_table->Release();
}
} l;
- WCHAR psz_w_graph_name[128];
+ WCHAR pwsz_graph_name[128];
HRESULT hr;
hr = ::GetRunningObjectTable( 0, &l.p_ro_table );
@@ -2041,11 +2940,11 @@ HRESULT BDAGraph::Register()
return hr;
}
- size_t len = sizeof(psz_w_graph_name) / sizeof(psz_w_graph_name[0]);
- _snwprintf( psz_w_graph_name, len - 1, L"VLC BDA Graph %08x Pid %08x",
+ size_t len = sizeof(pwsz_graph_name) / sizeof(pwsz_graph_name[0]);
+ _snwprintf( pwsz_graph_name, len - 1, L"VLC BDA Graph %08x Pid %08x",
(DWORD_PTR) p_filter_graph, ::GetCurrentProcessId() );
- psz_w_graph_name[len-1] = 0;
- hr = CreateItemMoniker( L"!", psz_w_graph_name, &l.p_moniker );
+ pwsz_graph_name[len-1] = 0;
+ hr = CreateItemMoniker( L"!", pwsz_graph_name, &l.p_moniker );
if( FAILED( hr ) )
{
msg_Warn( p_access, "Register: Cannot Create Moniker: hr=0x%8lx", hr );
@@ -2058,7 +2957,8 @@ HRESULT BDAGraph::Register()
msg_Warn( p_access, "Register: Cannot Register Graph: hr=0x%8lx", hr );
return hr;
}
-// msg_Dbg( p_access, "Register: registered Graph: %S", psz_w_graph_name );
+
+ msg_Dbg( p_access, "Register: registered Graph: %S", pwsz_graph_name );
return hr;
}
@@ -2067,8 +2967,51 @@ void BDAGraph::Deregister()
HRESULT hr;
IRunningObjectTable* p_ro_table;
hr = ::GetRunningObjectTable( 0, &p_ro_table );
+ /* docs say this does a Release() on d_graph_register stuff */
if( SUCCEEDED( hr ) )
p_ro_table->Revoke( d_graph_register );
d_graph_register = 0;
p_ro_table->Release();
}
+
+HRESULT BDAGraph::GetFilterName( IBaseFilter* p_filter, char** psz_bstr_name )
+{
+ FILTER_INFO filter_info;
+ HRESULT hr = S_OK;
+
+ hr = p_filter->QueryFilterInfo(&filter_info);
+ if( FAILED( hr ) )
+ return hr;
+ int i_name_len = WideCharToMultiByte( CP_ACP, 0, filter_info.achName,
+ -1, *psz_bstr_name, 0, NULL, NULL );
+ *psz_bstr_name = new char[ i_name_len ];
+ i_name_len = WideCharToMultiByte( CP_ACP, 0, filter_info.achName,
+ -1, *psz_bstr_name, i_name_len, NULL, NULL );
+
+ // The FILTER_INFO structure holds a pointer to the Filter Graph
+ // Manager, with a reference count that must be released.
+ if( filter_info.pGraph )
+ filter_info.pGraph->Release();
+ return S_OK;
+}
+
+HRESULT BDAGraph::GetPinName( IPin* p_pin, char** psz_bstr_name )
+{
+ PIN_INFO pin_info;
+ HRESULT hr = S_OK;
+
+ hr = p_pin->QueryPinInfo(&pin_info);
+ if( FAILED( hr ) )
+ return hr;
+ int i_name_len = WideCharToMultiByte( CP_ACP, 0, pin_info.achName,
+ -1, *psz_bstr_name, 0, NULL, NULL );
+ *psz_bstr_name = new char[ i_name_len ];
+ i_name_len = WideCharToMultiByte( CP_ACP, 0, pin_info.achName,
+ -1, *psz_bstr_name, i_name_len, NULL, NULL );
+
+ // The PIN_INFO structure holds a pointer to the Filter,
+ // with a referenppce count that must be released.
+ if( pin_info.pFilter )
+ pin_info.pFilter->Release();
+ return S_OK;
+}
diff --git a/modules/access/dtv/bdagraph.hpp b/modules/access/dtv/bdagraph.hpp
index 0048cf5..aa438ee 100644
--- a/modules/access/dtv/bdagraph.hpp
+++ b/modules/access/dtv/bdagraph.hpp
@@ -66,6 +66,7 @@ public:
/* */
int SubmitTuneRequest(void);
+ unsigned EnumSystems(void);
int SetCQAM(long);
int SetATSC(long);
@@ -87,8 +88,10 @@ private:
STDMETHODIMP BufferCB( double d_time, BYTE* p_buffer, long l_buffer_len );
vlc_object_t *p_access;
- CLSID guid_network_type;
- long l_tuner_used; /* Index of the Tuning Device */
+ CLSID guid_network_type; /* network type in use */
+ long l_tuner_used; /* Index of the Tuning Device in use */
+ unsigned systems; /* bitmask of all tuners' network types */
+
/* registration number for the RunningObjectTable */
DWORD d_graph_register;
@@ -96,25 +99,39 @@ private:
IMediaControl* p_media_control;
IGraphBuilder* p_filter_graph;
- ITuningSpace* p_tuning_space;
- ITuneRequest* p_tune_request;
+ ITuningSpaceContainer* p_tuning_space_container;
+ ITuningSpace* p_tuning_space;
+ ITuneRequest* p_tune_request;
+
+ IDVBTuningSpace* p_dvb_tuning_space;
+ IDVBSTuningSpace* p_dvbs_tuning_space;
+#if 0
+ IDigitalCableTuningSpace* p_cqam_tuning_space;
+ IATSCTuningSpace* p_atsc_tuning_space;
+#endif
ICreateDevEnum* p_system_dev_enum;
IBaseFilter* p_network_provider;
- IScanningTuner* p_scanning_tuner;
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 CreateTuneRequest( );
+ HRESULT SetUpTuner( REFCLSID guid_this_network_type );
+ HRESULT GetNextNetworkType( CLSID* guid_this_network_type );
HRESULT Build( );
+ HRESULT Check( REFCLSID guid_this_network_type );
+ HRESULT GetFilterName( IBaseFilter* p_filter, char** psz_bstr_name );
+ HRESULT GetPinName( IPin* p_pin, char** psz_bstr_name );
+ unsigned GetSystem( REFCLSID clsid );
+ HRESULT ListFilters( REFCLSID this_clsid );
HRESULT FindFilter( REFCLSID clsid, long* i_moniker_used,
- IBaseFilter* p_upstream, IBaseFilter** p_p_downstream );
+ IBaseFilter* p_upstream, IBaseFilter** p_p_downstream);
HRESULT Connect( IBaseFilter* p_filter_upstream,
- IBaseFilter* p_filter_downstream );
+ IBaseFilter* p_filter_downstream);
HRESULT Start( );
HRESULT Destroy( );
HRESULT Register( );
diff --git a/modules/access/dtv/dtv.h b/modules/access/dtv/dtv.h
index 3cf6503..889ac84 100644
--- a/modules/access/dtv/dtv.h
+++ b/modules/access/dtv/dtv.h
@@ -28,6 +28,7 @@ extern "C" {
enum {
ATSC = 0x00000001,
+ CQAM = 0x00000002,
DVB_C = 0x00000010,
DVB_C2 = 0x00000020,
@@ -39,6 +40,8 @@ enum {
ISDB_C = 0x00001000,
ISDB_S = 0x00002000,
ISDB_T = 0x00004000,
+
+ UNIVERSAL = 0xffffffff,
};
typedef struct dvb_device dvb_device_t;
--
1.7.7.6
More information about the vlc-devel
mailing list