windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/msvidctl/bdatuner.cpp
2020-09-26 16:20:57 +08:00

229 lines
7.3 KiB
C++

//==========================================================================;
//
// Copyright (c) Microsoft Corporation 1999-2000.
//
//--------------------------------------------------------------------------;
//
// MSVidBDATuner.cpp : Implementation of CMSVidBDATuner
//
#include "stdafx.h"
#ifndef TUNING_MODEL_ONLY
#include "MSVidCtl.h"
#include "BDATuner.h"
DEFINE_EXTERN_OBJECT_ENTRY(CLSID_MSVidBDATunerDevice, CMSVidBDATuner)
/////////////////////////////////////////////////////////////////////////////
// CMSVidBDATuner
STDMETHODIMP CMSVidBDATuner::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IMSVidTuner,
&__uuidof(CMSVidBDATuner)
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
HRESULT CMSVidBDATuner::Unload(void) {
BroadcastUnadvise();
IMSVidGraphSegmentImpl<CMSVidBDATuner, MSVidSEG_SOURCE, &KSCATEGORY_BDA_RECEIVER_COMPONENT>::Unload();
m_iNetworkProvider = -1;
m_iTIF = -1;
return NOERROR;
}
HRESULT CMSVidBDATuner::UpdateTR(TNTuneRequest &tr) {
PQBDATuner pt(m_Filters[m_iNetworkProvider]);
return pt->get_TuneRequest(&tr);
}
HRESULT CMSVidBDATuner::DoTune(TNTuneRequest &tr) {
if (m_iNetworkProvider == -1) {
return S_FALSE;
}
PQBDATuner pt(m_Filters[m_iNetworkProvider]);
if (!pt) {
return Error(IDS_INVALID_TR, __uuidof(CMSVidBDATuner), DISP_E_TYPEMISMATCH);
}
return pt->put_TuneRequest(tr);
}
HRESULT CMSVidBDATuner::put_Container(IMSVidGraphSegmentContainer *pCtl) {
if (!m_fInit) {
return Error(IDS_OBJ_NO_INIT, __uuidof(CMSVidBDATuner), CO_E_NOTINITIALIZED);
}
try {
if (!pCtl) {
return Unload();
}
if (m_pContainer) {
if (!m_pContainer.IsEqualObject(VWSegmentContainer(pCtl))) {
return Error(IDS_OBJ_ALREADY_INIT, __uuidof(CMSVidBDATuner), CO_E_ALREADYINITIALIZED);
} else {
return NO_ERROR;
}
}
// DON'T addref the container. we're guaranteed nested lifetimes
// and an addref creates circular refcounts so we never unload.
m_pContainer.p = pCtl;
m_pGraph = m_pContainer.GetGraph();
if (!m_pCurrentTR) {
// if we don't have a tune request we can't tell what NP we need.
return Error(IDS_NO_NP, __uuidof(CMSVidBDATuner), E_FAIL);
}
// bring in the right network provider
if (!m_pSystemEnum) {
m_pSystemEnum = PQCreateDevEnum(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER);
}
DSDevices pnpenum(m_pSystemEnum, KSCATEGORY_BDA_NETWORK_PROVIDER);
if (!pnpenum) {
TRACELM(TRACE_ERROR, "CMSVidBDATuner::put_Container() can't create network provider category enumerator");
return Error(IDS_NO_NP_CAT, __uuidof(CMSVidBDATuner), E_FAIL);
}
DSDevices::iterator i = pnpenum.begin();
DSFilter np;
for (;i != pnpenum.end(); ++i) {
np = m_pGraph.AddMoniker(*i);
if (!np) {
continue;
}
PQTuner pt(np);
if (pt) {
HRESULT hr = pt->put_TuningSpace(m_pCurrentTR.TuningSpace());
if (SUCCEEDED(hr)) {
hr = pt->put_TuneRequest(m_pCurrentTR);
if (SUCCEEDED(hr)) {
break;
}
}
}
bool rc = m_pGraph.RemoveFilter(np);
if (!rc) {
return E_UNEXPECTED;
}
}
if (i == pnpenum.end()) {
TRACELM(TRACE_ERROR, "CMSVidBDATuner::put_Container() can't load network provider");
return Error(IDS_NO_NP, __uuidof(CMSVidBDATuner), E_FAIL);
}
_ASSERT(!!np);
m_Filters.push_back(np);
m_iNetworkProvider = m_Filters.size() - 1;
TRACELM(TRACE_DETAIL, "CMSVidBDATuner::put_Container() attempting to load tuners from KSCATEGORY_BDA_NETWORK_TUNER");
HRESULT hr = LoadTunerSection(np, KSCATEGORY_BDA_NETWORK_TUNER);
if (FAILED(hr)) {
TRACELM(TRACE_DETAIL, "CMSVidBDATuner::put_Container() attempting to load tuners from KSCATEGORY_BDA_RECEIVER_COMPONENT");
hr = LoadTunerSection(np, KSCATEGORY_BDA_RECEIVER_COMPONENT);
if (FAILED(hr)) {
m_Filters.clear();
m_iNetworkProvider = -1;
return hr;
}
}
hr = BroadcastAdvise();
if (FAILED(hr)) {
TRACELM(TRACE_ERROR, "CMSVidTVTuner::put_Container() can't advise for broadcast events");
return E_UNEXPECTED;
}
return NOERROR;
} catch (ComException &e) {
return e;
} catch(...) {
return E_UNEXPECTED;
}
return NOERROR;
}
HRESULT CMSVidBDATuner::LoadTunerSection(DSFilter& np, const GUID& kscategory) {
TRACELM(TRACE_DETAIL, "CMSVidBDATuner::LoadTunerSection()");
DSFilter tuner;
DSFilterList added;
DSDevices ptunerenum(m_pSystemEnum, kscategory);
DSDevices::iterator i = ptunerenum.begin();
for (; i != ptunerenum.end(); ++i) {
tuner = m_pGraph.AddMoniker(*i);
if (!tuner) {
continue;
}
// connect np to decode
HRESULT hr = m_pGraph.Connect(np, tuner, added);
if (FAILED(hr)) {
bool rc = m_pGraph.RemoveFilter(tuner);
if (!rc) {
return E_UNEXPECTED;
}
continue;
}
m_Filters.insert(m_Filters.end(), added.begin(), added.end());
added.clear();
// bring in the all right tifs
DSDevices ptife(m_pSystemEnum, KSCATEGORY_BDA_TRANSPORT_INFORMATION);
DSDevices::iterator itif = ptife.begin();
DSFilter tif;
int cTIFsAdded = 0;
for (;itif != ptife.end(); ++itif) {
tif = m_pGraph.AddMoniker(*itif);
if (!tif) {
continue;
}
// connect np to tif
hr = m_pGraph.Connect(np, tif, added);
if (FAILED(hr)) {
TRACELSM(TRACE_ERROR, (dbgDump << "CMSVidBDATuner::LoadTunerSection() can't connect network provider to transport information filter, trying next tif " << hr), "");
bool rc = m_pGraph.RemoveFilter(tif);
if (!rc) {
return E_UNEXPECTED;
}
} else {
++cTIFsAdded;
m_Filters.push_back(tif);
m_iTIF = m_Filters.size() - 1;
m_Filters.insert(m_Filters.end(), added.begin(), added.end());
added.clear();
}
}
if (cTIFsAdded) {
break;
}
// no tifs found for this "tuner", try the next one
bool rc = m_pGraph.RemoveFilter(tuner);
if (!rc) {
return E_UNEXPECTED;
}
}
if ( i == ptunerenum.end()) {
TRACELM(TRACE_ERROR, "CMSVidBDATuner::LoadTunerSection() can't connect network provider to any transport information filters.");
return Error(IDS_CANT_CONNECT_NP_TIF, __uuidof(CMSVidBDATuner), E_FAIL);
}
m_Filters.push_back(tuner);
m_iTuner = m_Filters.size() - 1;
return NOERROR;
}
HRESULT CMSVidBDATuner::Fire(GUID gEventID) {
TRACELM(TRACE_DETAIL, "CMSVidBDATuner::Fire()");
if (gEventID == EVENTID_TuningChanged) {
Fire_OnTuneChanged(this);
}
return NOERROR;
}
#endif //TUNING_MODEL_ONLY
// end of file - MSVidBDATuner.cpp