sync with trunk r46493
[reactos.git] / dll / directx / msdvbnp / scanningtuner.cpp
index 0c9b778..76665f6 100644 (file)
@@ -48,12 +48,19 @@ public:
     HRESULT STDMETHODCALLTYPE ScanDown(long MillisecondsPause);
     HRESULT STDMETHODCALLTYPE AutoProgram();
 
-    CScanningTunner() : m_Ref(0), m_TuningSpace(0){};
-    virtual ~CScanningTunner(){};
-
+    CScanningTunner(std::vector<IUnknown*> & DeviceFilters) : m_Ref(0), m_TuningSpace(0), m_DeviceFilters(DeviceFilters){};
+    virtual ~CScanningTunner() {};
+    HRESULT STDMETHODCALLTYPE StartChanges();
+    HRESULT STDMETHODCALLTYPE CommitChanges();
+    HRESULT STDMETHODCALLTYPE CheckChanges();
+    HRESULT STDMETHODCALLTYPE SetLnbInfo(IBDA_LNBInfo * pLnbInfo, ULONG ulLOFLow, ULONG ulLOFHigh, ULONG ulSwitchFrequency);
+    HRESULT STDMETHODCALLTYPE SetDigitalDemodulator(IBDA_DigitalDemodulator * pDigitalDemo, ModulationType ModType, FECMethod InnerFEC, BinaryConvolutionCodeRate InnerFECRate, FECMethod OuterFEC, BinaryConvolutionCodeRate OuterFECRate, ULONG SymbolRate);
+    HRESULT SetFrequency(IBDA_FrequencyFilter * pFrequency, ULONG FrequencyMultiplier, ULONG Frequency, Polarisation Polarity, ULONG Range, ULONG Bandwidth);
+    HRESULT STDMETHODCALLTYPE performDVBTTune(IDVBTuneRequest * pDVBTRequest, IDVBTLocator *pDVBTLocator);
 protected:
     LONG m_Ref;
     ITuningSpace * m_TuningSpace;
+    std::vector<IUnknown*> & m_DeviceFilters;
 };
 
 HRESULT
@@ -140,8 +147,48 @@ STDMETHODCALLTYPE
 CScanningTunner::put_TuneRequest(
     ITuneRequest *TuneRequest)
 {
-    OutputDebugStringW(L"CScanningTunner::put_TuneRequest : NotImplemented\n");
-    return E_NOTIMPL;
+    IDVBTuneRequest * pDVBTRequest;
+    ILocator *pLocator;
+    IDVBTLocator *pDVBTLocator;
+    HRESULT hr;
+    
+
+    OutputDebugStringW(L"CScanningTunner::put_TuneRequest\n");
+
+    // query for IDVBTuneRequest interface
+    hr = TuneRequest->QueryInterface(IID_IDVBTuneRequest, (void**)&pDVBTRequest);
+
+    // sanity check
+    assert(hr == NOERROR);
+
+    // get the IDVBTLocator
+    hr = pDVBTRequest->get_Locator((ILocator**)&pLocator);
+
+    // sanity check
+    assert(hr == NOERROR);
+    assert(pLocator);
+
+    hr = pLocator->QueryInterface(IID_ILocator, (void**)&pDVBTLocator);
+
+    // sanity check
+    assert(hr == NOERROR);
+
+
+    StartChanges();
+    CommitChanges();
+    StartChanges();
+
+    hr = performDVBTTune(pDVBTRequest, pDVBTLocator);
+
+
+    pDVBTLocator->Release();
+    pDVBTRequest->Release();
+
+    CheckChanges();
+    CommitChanges();
+    StartChanges();
+
+    return NOERROR;
 }
 
 HRESULT
@@ -233,20 +280,431 @@ CScanningTunner::AutoProgram()
     return E_NOTIMPL;
 }
 
+//-------------------------------------------------------------------
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::performDVBTTune(
+    IDVBTuneRequest * pDVBTRequest,
+    IDVBTLocator *pDVBTLocator)
+{
+    HRESULT hr;
+    ULONG Index;
+    IBDA_Topology *pTopo;
+    IUnknown *pNode;
+    IBDA_FrequencyFilter * pFrequency;
+    IBDA_LNBInfo * pLnbInfo;
+    IBDA_DigitalDemodulator *pDigitalDemo;
+    LONG BandWidth;
+    LONG Frequency;
+    LONG SymbolRate;
+    FECMethod InnerFEC, OuterFEC;
+    BinaryConvolutionCodeRate InnerFECRate, OuterFECRate;
+    ModulationType Modulation;
+
+    pDVBTLocator->get_Bandwidth(&BandWidth);
+    pDVBTLocator->get_CarrierFrequency(&Frequency);
+    pDVBTLocator->get_InnerFEC(&InnerFEC);
+    pDVBTLocator->get_InnerFECRate(&InnerFECRate);
+    pDVBTLocator->get_Modulation(&Modulation);
+    pDVBTLocator->get_OuterFEC(&OuterFEC);
+    pDVBTLocator->get_OuterFECRate(&OuterFECRate);
+    pDVBTLocator->get_SymbolRate(&SymbolRate);
+
+
+    WCHAR Buffer[1000];
+    swprintf(Buffer, L"BandWidth %lu Frequency %lu Rate %lu InnerFEC %ld OuterFEC %ld InnerFECRate %ld OuterFECRate %ld Modulation %lu\n",
+             BandWidth, Frequency, SymbolRate, InnerFEC, OuterFEC, InnerFECRate, OuterFECRate, Modulation);
+
+    OutputDebugStringW(Buffer);
+
+
+
+    for(Index = 0; Index < m_DeviceFilters.size(); Index++)
+    {
+        // get device filter
+        IUnknown * pFilter = m_DeviceFilters[Index];
+
+        if (!pFilter)
+            continue;
+
+        hr = pFilter->QueryInterface(IID_IBDA_Topology, (void**)&pTopo);
+        // sanity check
+        assert(hr == NOERROR);
+
+        pNode = NULL;
+        hr = pTopo->GetControlNode(0, 1, 0, &pNode); //HACK
+
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune GetControlNode %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        if (FAILED(hr))
+            continue;
+
+        // sanity check
+        assert(hr == NOERROR);
+        assert(pNode);
+
+        hr = pNode->QueryInterface(IID_IBDA_FrequencyFilter, (void**)&pFrequency);
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_FrequencyFilter hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        hr = SetFrequency(pFrequency, 1000 /* FIXME */, Frequency, BDA_POLARISATION_NOT_DEFINED /* FIXME */, BDA_RANGE_NOT_SET /* FIXME */, BandWidth);
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune SetFrequency hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        //sanity check
+        assert(hr == NOERROR);
+
+        // release interface
+        pFrequency->Release();
+
+
+        hr = pNode->QueryInterface(IID_IBDA_LNBInfo, (void**)&pLnbInfo);
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_LNBInfo hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        hr = SetLnbInfo(pLnbInfo, ULONG_MAX /* FIXME */, ULONG_MAX /* FIXME*/, ULONG_MAX /*FIXME*/);
+
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune SetLnbInfo hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        // release interface
+        pLnbInfo->Release();
+
+        hr = pNode->QueryInterface(IID_IBDA_DigitalDemodulator, (void**)&pDigitalDemo);
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune IID_IBDA_DigitalDemodulator hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        hr = SetDigitalDemodulator(pDigitalDemo, Modulation, InnerFEC, InnerFECRate, OuterFEC, OuterFECRate, SymbolRate);
+
+        swprintf(Buffer, L"CScanningTunner::performDVBTTune SetDigitalDemodulator hr %lx\n", hr);
+        OutputDebugStringW(Buffer);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        // release interface
+        pDigitalDemo->Release();
+
+        // release control node
+        pNode->Release();
+
+        // release IBDA_Topology;
+        pTopo->Release();
+
+    }
+    return hr;
+}
+
+
+
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::CheckChanges()
+{
+    ULONG Index;
+    HRESULT hResult = NOERROR;
+    IBDA_DeviceControl * pDeviceControl;
+
+    for(Index = 0; Index < m_DeviceFilters.size(); Index++)
+    {
+        // get filter
+        IUnknown * pFilter = m_DeviceFilters[Index];
+
+        if (!pFilter)
+            continue;
+
+        // query for IBDA_DeviceControl interface
+        hResult = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
+
+        // sanity check
+        assert(hResult == NOERROR);
+
+        //start changes
+        hResult = pDeviceControl->CheckChanges();
+
+        // fix for unimplemented
+        if (hResult == E_NOTIMPL)
+            hResult = NOERROR;
+
+        // release interface
+        pDeviceControl->Release();
+
+        if (FAILED(hResult))
+        {
+            //shouldnt happen
+            break;
+        }
+    }
+    // done
+    return hResult;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::CommitChanges()
+{
+    ULONG Index;
+    HRESULT hResult = NOERROR;
+    IBDA_DeviceControl * pDeviceControl;
+
+    for(Index = 0; Index < m_DeviceFilters.size(); Index++)
+    {
+        // get filter
+        IUnknown * pFilter = m_DeviceFilters[Index];
+
+        if (!pFilter)
+            continue;
+
+        // query for IBDA_DeviceControl interface
+        HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        //start changes
+        hr = pDeviceControl->CommitChanges();
+
+        // fix for unimplemented
+        if (hr == E_NOTIMPL)
+            hr = NOERROR;
+
+        if (FAILED(hr))
+        {
+            pDeviceControl->StartChanges();
+            pDeviceControl->CommitChanges();
+            hResult = E_UNEXPECTED;
+        }
+
+        // release interface
+        pDeviceControl->Release();
+
+    }
+
+    //done
+    return hResult;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::StartChanges()
+{
+    ULONG Index;
+    IBDA_DeviceControl * pDeviceControl;
+
+    for(Index = 0; Index < m_DeviceFilters.size(); Index++)
+    {
+        // get filter
+        IUnknown * pFilter = m_DeviceFilters[Index];
+
+        if (!pFilter)
+            continue;
+
+        // query for IBDA_DeviceControl interface
+        HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        //start changes
+        hr = pDeviceControl->StartChanges();
+
+        // release interface
+        pDeviceControl->Release();
+
+        // fix for unimplemented
+        if (hr == E_NOTIMPL)
+            hr = NOERROR;
+
+        if (FAILED(hr))
+            return hr;
+
+    }
+
+    // now commit the changes
+    for(Index = 0; Index < m_DeviceFilters.size(); Index++)
+    {
+        // get filter
+        IUnknown * pFilter = m_DeviceFilters[Index];
+
+        if (!pFilter)
+            continue;
+
+        // query for IBDA_DeviceControl interface
+        HRESULT hr = pFilter->QueryInterface(IID_IBDA_DeviceControl, (void**)&pDeviceControl);
+
+        // sanity check
+        assert(hr == NOERROR);
+
+        hr = pDeviceControl->CommitChanges();
+
+        // release interface
+        pDeviceControl->Release();
+    }
+
+    // done
+    return NOERROR;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::SetLnbInfo(
+    IBDA_LNBInfo * pLnbInfo,
+    ULONG ulLOFLow,
+    ULONG ulLOFHigh,
+    ULONG ulSwitchFrequency)
+{
+    HRESULT hr;
+
+    hr = pLnbInfo->put_LocalOscilatorFrequencyLowBand(ulLOFLow);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+
+    if (FAILED(hr))
+        return hr;
+
+    hr = pLnbInfo->put_LocalOscilatorFrequencyHighBand(ulLOFHigh);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+
+    if (FAILED(hr))
+        return hr;
+
+    hr = pLnbInfo->put_HighLowSwitchFrequency(ulSwitchFrequency);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+
+    return hr;
+}
+
+HRESULT
+CScanningTunner::SetFrequency(
+    IBDA_FrequencyFilter * pFrequency,
+    ULONG FrequencyMultiplier,
+    ULONG Frequency,
+    Polarisation Polarity,
+    ULONG Range,
+    ULONG Bandwidth)
+{
+    HRESULT hr;
+
+    hr = pFrequency->put_FrequencyMultiplier(FrequencyMultiplier);
+    if (FAILED(hr))
+        return hr;
+
+    hr = pFrequency->put_Frequency(Frequency);
+    if (FAILED(hr))
+        return hr;
+
+    hr = pFrequency->put_Polarity(Polarity);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
+        hr = NOERROR;
+
+    if (FAILED(hr))
+        return hr;
+
+    hr = pFrequency->put_Range(Range);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND))
+        hr = NOERROR;
+
+    if (FAILED(hr))
+        return hr;
+
+    hr = pFrequency->put_Bandwidth(Bandwidth);
+    return hr;
+}
+
+HRESULT
+STDMETHODCALLTYPE
+CScanningTunner::SetDigitalDemodulator(
+    IBDA_DigitalDemodulator * pDigitalDemo,
+    ModulationType ModType,
+    FECMethod InnerFEC,
+    BinaryConvolutionCodeRate InnerFECRate,
+    FECMethod OuterFEC,
+    BinaryConvolutionCodeRate OuterFECRate,
+    ULONG SymbolRate)
+{
+    HRESULT hr;
+
+    hr = pDigitalDemo->put_ModulationType(&ModType);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+
+    if (FAILED(hr))
+        return hr;
+
+    hr = pDigitalDemo->put_InnerFECMethod(&InnerFEC);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+    if (FAILED(hr))
+        return hr;
+
+    hr = pDigitalDemo->put_InnerFECRate(&InnerFECRate);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+    if (FAILED(hr))
+        return hr;
+
+    hr = pDigitalDemo->put_OuterFECMethod(&OuterFEC);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+    if (FAILED(hr))
+        return hr;
+
+    hr = pDigitalDemo->put_OuterFECRate(&OuterFECRate);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+    if (FAILED(hr))
+        return hr;
+
+    hr = pDigitalDemo->put_SymbolRate(&SymbolRate);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+    if (FAILED(hr))
+        return hr;
+
+    SpectralInversion Inversion = BDA_SPECTRAL_INVERSION_NOT_DEFINED;
+    hr = pDigitalDemo->put_SpectralInversion(&Inversion);
+    if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND))
+        hr = NOERROR;
+
+    return hr;
+}
+
+
 HRESULT
 WINAPI
 CScanningTunner_fnConstructor(
-    IUnknown *pUnknown,
+    std::vector<IUnknown*> & DeviceFilter,
     REFIID riid,
     LPVOID * ppv)
 {
-    CScanningTunner * handler = new CScanningTunner();
+    CScanningTunner * handler = new CScanningTunner(DeviceFilter);
 
 #ifdef MSDVBNP_TRACE
     WCHAR Buffer[MAX_PATH];
     LPOLESTR lpstr;
     StringFromCLSID(riid, &lpstr);
-    swprintf(Buffer, L"CScanningTunner_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown);
+    swprintf(Buffer, L"CScanningTunner_fnConstructor riid %s\n", lpstr);
     OutputDebugStringW(Buffer);
 #endif