]> git.sesse.net Git - vlc/blobdiff - modules/access/bda/bdagraph.cpp
Remove unneded test before delete/free.
[vlc] / modules / access / bda / bdagraph.cpp
index f536923cd49fb845bf5c42f778b3e2fe99c1bfa6..929ae1146776691859fc542270ed715817a26575 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <vlc/vlc.h>
-#include <vlc_input.h>
-#include <vlc_access.h>
-
-/* Needed to call CoInitializeEx */
-#define _WIN32_DCOM
-
-/* Work-around a bug in w32api-2.5 */
-/*#ifndef _MSC_VER
-#   define QACONTAINERFLAGS QACONTAINERFLAGS_SOMETHINGELSE
-#endif */
-
 #include "bdagraph.h"
-
-const GUID CLSID_ATSCLocator           =
-    {0x8872FF1B,0x98FA,0x4D7A,{0x8D,0x93,0xC9,0xF1,0x05,0x5F,0x85,0xBB}};
-const GUID CLSID_ATSCNetworkProvider   =
-    {0x0dad2fdd,0x5fd7,0x11d3,{0x8f,0x50,0x00,0xc0,0x4f,0x79,0x71,0xe2}};
-const GUID CLSID_DVBCLocator           =
-    {0xc531d9fd,0x9685,0x4028,{0x8b,0x68,0x6e,0x12,0x32,0x07,0x9f,0x1e}};
-const GUID CLSID_DVBCNetworkProvider   =
-    {0xdc0c0fe7,0x0485,0x4266,{0xb9,0x3f,0x68,0xfb,0xf8,0xe,0xd8,0x34}};
-const GUID CLSID_DVBSLocator           =
-    {0x1df7d126,0x4050,0x47f0,{0xa7,0xcf,0x4c,0x4c,0xa9,0x24,0x13,0x33}};
-const GUID CLSID_DVBSNetworkProvider   =
-    {0xfa4b375a,0x45b4,0x4d45,{0x84,0x40,0x26,0x39,0x57,0xb1,0x16,0x23}};
-const GUID CLSID_DVBSTuningSpace       =
-    {0xb64016f3,0xc9a2,0x4066,{0x96,0xf0,0xbd,0x95,0x63,0x31,0x47,0x26}};
-const GUID CLSID_DVBTLocator           =
-    {0x9cd64701,0xbdf3,0x4d14,{0x8e,0x03,0xf1,0x29,0x83,0xd8,0x66,0x64}};
-const GUID CLSID_DVBTNetworkProvider   =
-    {0x216c62df,0x6d7f,0x4e9a,{0x85,0x71,0x05,0xf1,0x4e,0xdb,0x76,0x6a}};
-const GUID CLSID_FilterGraph           =
-    {0xe436ebb3,0x524f,0x11ce,{0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
-const GUID CLSID_InfTee                =
-    {0xf8388a40,0xd5bb,0x11d0,{0xbe,0x5a,0x00,0x80,0xc7,0x06,0x56,0x8e}};
-const GUID CLSID_MPEG2Demultiplexer    =
-    {0xafb6c280,0x2c41,0x11d3,{0x8a,0x60,0x00,0x00,0xf8,0x1e,0x0e,0x4a}};
-const GUID CLSID_NullRenderer          =
-    {0xc1f400a4,0x3f08,0x11d3,{0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37}};
-const GUID CLSID_SampleGrabber         =
-    {0xc1f400a0,0x3f08,0x11d3,{0x9f,0x0b,0x00,0x60,0x08,0x03,0x9e,0x37}};
-const GUID CLSID_SystemDeviceEnum      =
-    {0x62be5d10,0x60eb,0x11d0,{0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86}};
-const GUID CLSID_SystemTuningSpaces    =
-    {0xd02aac50,0x027e,0x11d3,{0x9d,0x8e,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
-
-const GUID IID_IATSCChannelTuneRequest =
-    {0x0369B4E1,0x45B6,0x11d3,{0xB6,0x50,0x00,0xC0,0x4F,0x79,0x49,0x8E}};
-const GUID IID_IATSCLocator            =
-    {0xbf8d986f,0x8c2b,0x4131,{0x94,0xd7,0x4d,0x3d,0x9f,0xcc,0x21,0xef}};
-const GUID IID_IBaseFilter             =
-    {0x56a86895,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
-const GUID IID_ICreateDevEnum          =
-    {0x29840822,0x5b84,0x11d0,{0xbd,0x3b,0x00,0xa0,0xc9,0x11,0xce,0x86}};
-const GUID IID_IDVBTLocator            =
-    {0x8664da16,0xdda2,0x42ac,{0x92,0x6a,0xc1,0x8f,0x91,0x27,0xc3,0x02}};
-const GUID IID_IDVBCLocator            =
-    {0x6e42f36e,0x1dd2,0x43c4,{0x9f,0x78,0x69,0xd2,0x5a,0xe3,0x90,0x34}};
-const GUID IID_IDVBSLocator            =
-    {0x3d7c353c,0x0d04,0x45f1,{0xa7,0x42,0xf9,0x7c,0xc1,0x18,0x8d,0xc8}};
-const GUID IID_IDVBSTuningSpace        =
-    {0xcdf7be60,0xd954,0x42fd,{0xa9,0x72,0x78,0x97,0x19,0x58,0xe4,0x70}};
-const GUID IID_IDVBTuneRequest         =
-    {0x0D6F567E,0xA636,0x42bb,{0x83,0xBA,0xCE,0x4C,0x17,0x04,0xAF,0xA2}};
-const GUID IID_IGraphBuilder           =
-    {0x56a868a9,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
-const GUID IID_IMediaControl           =
-    {0x56a868b1,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
-const GUID IID_IMpeg2Demultiplexer     =
-    {0x436eee9c,0x264f,0x4242,{0x90,0xe1,0x4e,0x33,0x0c,0x10,0x75,0x12}};
-const GUID IID_ISampleGrabber          =
-    {0x6b652fff,0x11fe,0x4fce,{0x92,0xad,0x02,0x66,0xb5,0xd7,0xc7,0x8f}};
-const GUID IID_IScanningTuner          =
-    {0x1dfd0a5c,0x0284,0x11d3,{0x9d,0x8e,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
-const GUID IID_ITuner                  =
-    {0x28C52640,0x018A,0x11d3,{0x9D,0x8E,0x00,0xC0,0x4F,0x72,0xD9,0x80}};
-const GUID IID_ITuningSpace            =
-    {0x061c6e30,0xe622,0x11d2,{0x94,0x93,0x00,0xc0,0x4f,0x72,0xd9,0x80}};
-const GUID IID_ITuningSpaceContainer   =
-    {0x5B692E84,0xE2F1,0x11d2,{0x94,0x93,0x00,0xC0,0x4F,0x72,0xD9,0x80}};
-
-const GUID KSCATEGORY_BDA_TRANSPORT_INFORMATION =
-    {0xa2e3074f,0x6c3d,0x11d3,{0xb6,0x53,0x00,0xc0,0x4f,0x79,0x49,0x8e}};
-const GUID KSCATEGORY_BDA_RECEIVER_COMPONENT    =
-    {0xFD0A5AF4,0xB41D,0x11d2,{0x9c,0x95,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
-const GUID KSCATEGORY_BDA_NETWORK_TUNER         =
-    {0x71985f48,0x1ca1,0x11d3,{0x9c,0xc8,0x00,0xc0,0x4f,0x79,0x71,0xe0}};
-const GUID MEDIATYPE_MPEG2_SECTIONS             =
-    {0x455f176c,0x4b06,0x47ce,{0x9a,0xef,0x8c,0xae,0xf7,0x3d,0xf7,0xb5}};
-const GUID MEDIASUBTYPE_None                    =
-    {0xe436eb8e,0x524f,0x11ce,{0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
-const GUID FORMAT_None                          =
-    {0x0f6417d6,0xc318,0x11d0,{0xa4,0x3f,0x00,0xa0,0xc9,0x22,0x31,0x96}};
+#include <ctype.h>
 
 /****************************************************************************
  * Interfaces for calls from C
@@ -139,35 +43,46 @@ extern "C" {
 
     int dvb_SubmitATSCTuneRequest( access_t* p_access )
     {
-        return p_access->p_sys->p_bda_module->SubmitATSCTuneRequest();
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->SubmitATSCTuneRequest();
+        return VLC_EGENERIC;
     };
 
     int dvb_SubmitDVBTTuneRequest( access_t* p_access )
     {
-        return p_access->p_sys->p_bda_module->SubmitDVBTTuneRequest();
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->SubmitDVBTTuneRequest();
+        return VLC_EGENERIC;
     };
 
     int dvb_SubmitDVBCTuneRequest( access_t* p_access )
     {
-        return p_access->p_sys->p_bda_module->SubmitDVBCTuneRequest();
-    };    
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->SubmitDVBCTuneRequest();
+        return VLC_EGENERIC;
+    };
 
     int dvb_SubmitDVBSTuneRequest( access_t* p_access )
     {
-        return p_access->p_sys->p_bda_module->SubmitDVBSTuneRequest();
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->SubmitDVBSTuneRequest();
+        return VLC_EGENERIC;
     };
 
     long dvb_GetBufferSize( access_t* p_access )
     {
-        return p_access->p_sys->p_bda_module->GetBufferSize();
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->GetBufferSize();
+        return -1;
     };
 
     long dvb_ReadBuffer( access_t* p_access, long* l_buffer_len, BYTE* p_buff )
     {
-        return p_access->p_sys->p_bda_module->ReadBuffer( l_buffer_len, 
-            p_buff );
+        if( p_access->p_sys->p_bda_module )
+            return p_access->p_sys->p_bda_module->ReadBuffer( l_buffer_len,
+                p_buff );
+        return -1;
     };
-
 };
 
 /*****************************************************************************
@@ -179,6 +94,7 @@ BDAGraph::BDAGraph( access_t* p_this ):
     l_tuner_used(-1),
     d_graph_register( 0 )
 {
+    b_ready = FALSE;
     p_tuning_space = NULL;
     p_tune_request = NULL;
     p_media_control = NULL;
@@ -224,13 +140,14 @@ int BDAGraph::SubmitATSCTuneRequest()
         }
     } l;
     long l_major_channel, l_minor_channel, l_physical_channel;
+    long l_frequency;
 
     l_major_channel = l_minor_channel = l_physical_channel = -1;
-/*
+    l_frequency = -1;
     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" );
-*/
+    l_frequency = var_GetInteger( p_access, "dvb-frequency" );
 
     guid_network_type = CLSID_ATSCNetworkProvider;
     hr = CreateTuneRequest();
@@ -259,6 +176,8 @@ int BDAGraph::SubmitATSCTuneRequest()
     }
 
     hr = S_OK;
+    if( l_frequency > 0 )
+        hr = l.p_atsc_locator->put_CarrierFrequency( l_frequency );
     if( l_major_channel > 0 )
         hr = l.p_atsc_tune_request->put_Channel( l_major_channel );
     if( SUCCEEDED( hr ) && l_minor_channel > 0 )
@@ -319,11 +238,70 @@ int BDAGraph::SubmitDVBTTuneRequest()
                 p_dvbt_locator->Release();
         }
     } l;
-    long l_frequency, l_bandwidth;
-
-    l_frequency = l_bandwidth = -1;
+    long l_frequency, l_bandwidth, l_hp_fec, l_lp_fec, l_guard;
+    long l_transmission, l_hierarchy;
+    BinaryConvolutionCodeRate i_hp_fec, i_lp_fec;
+    GuardInterval             i_guard;
+    TransmissionMode          i_transmission;
+    HierarchyAlpha            i_hierarchy;
+
+    l_frequency = l_bandwidth = l_hp_fec = l_lp_fec = l_guard = -1;
+    l_transmission = l_hierarchy = -1;
     l_frequency = var_GetInteger( p_access, "dvb-frequency" );
     l_bandwidth = var_GetInteger( p_access, "dvb-bandwidth" );
+    l_hp_fec = var_GetInteger( p_access, "dvb-code-rate-hp" );
+    l_lp_fec = var_GetInteger( p_access, "dvb-code-rate-lp" );
+    l_guard = var_GetInteger( p_access, "dvb-guard" );
+    l_transmission = var_GetInteger( p_access, "dvb-transmission" );
+    l_hierarchy = var_GetInteger( p_access, "dvb-hierarchy" );
+
+    i_hp_fec = BDA_BCC_RATE_NOT_SET;
+    if( l_hp_fec == 1 )
+        i_hp_fec = BDA_BCC_RATE_1_2;
+    if( l_hp_fec == 2 )
+        i_hp_fec = BDA_BCC_RATE_2_3;
+    if( l_hp_fec == 3 )
+        i_hp_fec = BDA_BCC_RATE_3_4;
+    if( l_hp_fec == 4 )
+        i_hp_fec = BDA_BCC_RATE_5_6;
+    if( l_hp_fec == 5 )
+        i_hp_fec = BDA_BCC_RATE_7_8;
+
+    i_lp_fec = BDA_BCC_RATE_NOT_SET;
+    if( l_lp_fec == 1 )
+        i_lp_fec = BDA_BCC_RATE_1_2;
+    if( l_lp_fec == 2 )
+        i_lp_fec = BDA_BCC_RATE_2_3;
+    if( l_lp_fec == 3 )
+        i_lp_fec = BDA_BCC_RATE_3_4;
+    if( l_lp_fec == 4 )
+        i_lp_fec = BDA_BCC_RATE_5_6;
+    if( l_lp_fec == 5 )
+        i_lp_fec = BDA_BCC_RATE_7_8;
+
+    i_guard = BDA_GUARD_NOT_SET;
+    if( l_guard == 32 )
+        i_guard = BDA_GUARD_1_32;
+    if( l_guard == 16 )
+        i_guard = BDA_GUARD_1_16;
+    if( l_guard == 8 )
+        i_guard = BDA_GUARD_1_8;
+    if( l_guard == 4 )
+        i_guard = BDA_GUARD_1_4;
+
+    i_transmission = BDA_XMIT_MODE_NOT_SET;
+    if( l_transmission == 2 )
+        i_transmission = BDA_XMIT_MODE_2K;
+    if( l_transmission == 8 )
+        i_transmission = BDA_XMIT_MODE_8K;
+
+    i_hierarchy = BDA_HALPHA_NOT_SET;
+    if( l_hierarchy == 1 )
+        i_hierarchy = BDA_HALPHA_1;
+    if( l_hierarchy == 2 )
+        i_hierarchy = BDA_HALPHA_2;
+    if( l_hierarchy == 4 )
+        i_hierarchy = BDA_HALPHA_4;
 
     guid_network_type = CLSID_DVBTNetworkProvider;
     hr = CreateTuneRequest();
@@ -360,6 +338,16 @@ int BDAGraph::SubmitDVBTTuneRequest()
         hr = l.p_dvbt_locator->put_CarrierFrequency( l_frequency );
     if( SUCCEEDED( hr ) && l_bandwidth > 0 )
         hr = l.p_dvbt_locator->put_Bandwidth( l_bandwidth );
+    if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
+        hr = l.p_dvbt_locator->put_InnerFECRate( i_hp_fec );
+    if( SUCCEEDED( hr ) && i_lp_fec != BDA_BCC_RATE_NOT_SET )
+        hr = l.p_dvbt_locator->put_LPInnerFECRate( i_lp_fec );
+    if( SUCCEEDED( hr ) && i_guard != BDA_GUARD_NOT_SET )
+        hr = l.p_dvbt_locator->put_Guard( i_guard );
+    if( SUCCEEDED( hr ) && i_transmission != BDA_XMIT_MODE_NOT_SET )
+        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: "\
@@ -519,45 +507,123 @@ int BDAGraph::SubmitDVBSTuneRequest()
         public:
         IDVBTuneRequest* p_dvbs_tune_request;
         IDVBSLocator* p_dvbs_locator;
-        localComPtr(): p_dvbs_tune_request(NULL), p_dvbs_locator(NULL) {};
+        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),
+            p_dvbs_tuning_space(NULL), bstr_input_range(NULL),
+            pwsz_input_range(NULL), i_range_len(NULL), psz_polarisation(NULL),
+            psz_input_range(NULL) {};
         ~localComPtr()
         {
+            if( p_dvbs_tuning_space )
+                p_dvbs_tuning_space->Release();
             if( p_dvbs_tune_request )
                 p_dvbs_tune_request->Release();
             if( p_dvbs_locator )
                 p_dvbs_locator->Release();
+            SysFreeString( bstr_input_range );
+            delete pwsz_input_range;
+            free(pwsz_input_range);
+            free(pwsz_input_range);
         }
     } l;
     long l_frequency, l_symbolrate, l_azimuth, l_elevation, l_longitude;
-    char* psz_polarisation;
+    long l_lnb_lof1, l_lnb_lof2, l_lnb_slof, l_inversion, l_network_id;
+    long l_input_range, l_hp_fec;
+    int  i_mod;
     Polarisation i_polar;
+    SpectralInversion i_inversion;
     VARIANT_BOOL b_west;
+    BinaryConvolutionCodeRate i_hp_fec;
+    ModulationType i_mod_typ;
 
     l_frequency = l_symbolrate = l_azimuth = l_elevation = l_longitude = -1;
+    l_lnb_lof1 = l_lnb_lof2 = l_lnb_slof = l_inversion = l_network_id = -1;
+    l_input_range = l_hp_fec = i_mod = -1;
     l_frequency = var_GetInteger( p_access, "dvb-frequency" );
     l_symbolrate = var_GetInteger( p_access, "dvb-srate" );
     l_azimuth = var_GetInteger( p_access, "dvb-azimuth" );
     l_elevation = var_GetInteger( p_access, "dvb-elevation" );
     l_longitude = var_GetInteger( p_access, "dvb-longitude" );
-    psz_polarisation = var_GetString( p_access, "dvb-polarisation" );
+    l_lnb_lof1 = var_GetInteger( p_access, "dvb-lnb-lof1" );
+    l_lnb_lof2 = var_GetInteger( p_access, "dvb-lnb-lof2" );
+    l_lnb_slof = var_GetInteger( p_access, "dvb-lnb-slof" );
+    l.psz_polarisation = var_GetNonEmptyString( p_access, "dvb-polarisation" );
+    i_mod = var_GetInteger( p_access, "dvb-modulation" );
+    l_hp_fec = var_GetInteger( p_access, "dvb-code-rate-hp" );
+    l_inversion = var_GetInteger( p_access, "dvb-inversion" );
+    l_network_id = var_GetInteger( p_access, "dvb-network-id" );
+    l.psz_input_range = var_GetNonEmptyString( p_access, "dvb-range" );
 
     b_west = ( l_longitude < 0 ) ? TRUE : FALSE;
 
     i_polar = BDA_POLARISATION_NOT_SET;
-    if( *psz_polarisation == 'H' || *psz_polarisation == 'h' )
-        i_polar = BDA_POLARISATION_LINEAR_H;
-    if( *psz_polarisation == 'V' || *psz_polarisation == 'v' )
-        i_polar = BDA_POLARISATION_LINEAR_V;
-    if( *psz_polarisation == 'L' || *psz_polarisation == 'l' )
-        i_polar = BDA_POLARISATION_CIRCULAR_L;
-    if( *psz_polarisation == 'R' || *psz_polarisation == 'r' )
-        i_polar = BDA_POLARISATION_CIRCULAR_R;
+    if( l.psz_polarisation != NULL )
+        switch( toupper( l.psz_polarisation[0] ) )
+        {
+            case 'H':
+                i_polar = BDA_POLARISATION_LINEAR_H;
+                break;
+            case 'V':
+                i_polar = BDA_POLARISATION_LINEAR_V;
+                break;
+            case 'L':
+                i_polar = BDA_POLARISATION_CIRCULAR_L;
+                break;
+            case 'R':
+                i_polar = BDA_POLARISATION_CIRCULAR_R;
+                break;
+        }
+
+    i_inversion = BDA_SPECTRAL_INVERSION_NOT_SET;
+    if( l_inversion == 0 )
+        i_inversion = BDA_SPECTRAL_INVERSION_NORMAL;
+    if( l_inversion == 1 )
+        i_inversion = BDA_SPECTRAL_INVERSION_INVERTED;
+    if( l_inversion == 2 )
+        i_inversion = BDA_SPECTRAL_INVERSION_AUTOMATIC;
+
+    i_mod_typ = BDA_MOD_NOT_SET;
+    if( i_mod == 16 )
+        i_mod_typ = BDA_MOD_16QAM;
+    if( i_mod == 128 )
+        i_mod_typ = BDA_MOD_128QAM;
+    if( i_mod == 256 )
+        i_mod_typ = BDA_MOD_256QAM;
+    if( i_mod == 10004 )
+        i_mod_typ = BDA_MOD_QPSK;
+
+    i_hp_fec = BDA_BCC_RATE_NOT_SET;
+    if( l_hp_fec == 1 )
+        i_hp_fec = BDA_BCC_RATE_1_2;
+    if( l_hp_fec == 2 )
+        i_hp_fec = BDA_BCC_RATE_2_3;
+    if( l_hp_fec == 3 )
+        i_hp_fec = BDA_BCC_RATE_3_4;
+    if( l_hp_fec == 4 )
+        i_hp_fec = BDA_BCC_RATE_5_6;
+    if( l_hp_fec == 5 )
+        i_hp_fec = BDA_BCC_RATE_7_8;
+
+    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 )
+    {
+        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 );
+    }
 
     guid_network_type = CLSID_DVBSNetworkProvider;
     hr = CreateTuneRequest();
     if( FAILED( hr ) )
     {
-        msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
             "Cannot create Tune Request: hr=0x%8lx", hr );
         return VLC_EGENERIC;
     }
@@ -566,7 +632,7 @@ int BDAGraph::SubmitDVBSTuneRequest()
         (void**)&l.p_dvbs_tune_request );
     if( FAILED( hr ) )
     {
-        msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
             "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
         return VLC_EGENERIC;
     }
@@ -578,29 +644,56 @@ int BDAGraph::SubmitDVBSTuneRequest()
         IID_IDVBSLocator, (void**)&l.p_dvbs_locator );
     if( FAILED( hr ) )
     {
-        msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
             "Cannot create the DVBS Locator: hr=0x%8lx", hr );
         return VLC_EGENERIC;
     }
 
+    hr = p_tuning_space->QueryInterface( IID_IDVBSTuningSpace,
+        (void**)&l.p_dvbs_tuning_space );
+    if( FAILED( hr ) )
+    {
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
+            "Cannot QI for IDVBSTuningSpace: hr=0x%8lx", hr );
+        return VLC_EGENERIC;
+    }
+
     hr = S_OK;
-    if( l_frequency > 0 )
+    if( l_lnb_lof1 > 0 )
+        hr = l.p_dvbs_tuning_space->put_LowOscillator( l_lnb_lof1 );
+    if( SUCCEEDED( hr ) && l_lnb_slof > 0 )
+        hr = l.p_dvbs_tuning_space->put_LNBSwitch( l_lnb_slof );
+    if( SUCCEEDED( hr ) && l_lnb_lof2 > 0 )
+        hr = l.p_dvbs_tuning_space->put_HighOscillator( l_lnb_lof2 );
+    if( SUCCEEDED( hr ) && i_inversion != BDA_SPECTRAL_INVERSION_NOT_SET )
+        hr = l.p_dvbs_tuning_space->put_SpectralInversion( i_inversion );
+    if( SUCCEEDED( hr ) && l_network_id > 0 )
+        hr = l.p_dvbs_tuning_space->put_NetworkID( l_network_id );
+    if( SUCCEEDED( hr ) && l.i_range_len > 0 )
+        hr = l.p_dvbs_tuning_space->put_InputRange( l.bstr_input_range );
+
+    if( SUCCEEDED( hr ) && l_frequency > 0 )
         hr = l.p_dvbs_locator->put_CarrierFrequency( l_frequency );
     if( SUCCEEDED( hr ) && l_symbolrate > 0 )
         hr = l.p_dvbs_locator->put_SymbolRate( l_symbolrate );
+    if( SUCCEEDED( hr ) && i_polar != BDA_POLARISATION_NOT_SET )
+        hr = l.p_dvbs_locator->put_SignalPolarisation( i_polar );
+    if( SUCCEEDED( hr ) && i_mod_typ != BDA_MOD_NOT_SET )
+        hr = l.p_dvbs_locator->put_Modulation( i_mod_typ );
+    if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
+        hr = l.p_dvbs_locator->put_InnerFECRate( i_hp_fec );
+
     if( SUCCEEDED( hr ) && l_azimuth > 0 )
         hr = l.p_dvbs_locator->put_Azimuth( l_azimuth );
     if( SUCCEEDED( hr ) && l_elevation > 0 )
         hr = l.p_dvbs_locator->put_Elevation( l_elevation );
-    if( SUCCEEDED( hr ) )
-        hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
     if( SUCCEEDED( hr ) )
         hr = l.p_dvbs_locator->put_WestPosition( b_west );
-    if( SUCCEEDED( hr ) && i_polar != BDA_POLARISATION_NOT_SET )
-        hr = l.p_dvbs_locator->put_SignalPolarisation( i_polar );
+    if( SUCCEEDED( hr ) )
+        hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
     if( FAILED( hr ) )
     {
-        msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
             "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
         return VLC_EGENERIC;
     }
@@ -608,7 +701,7 @@ int BDAGraph::SubmitDVBSTuneRequest()
     hr = p_tune_request->put_Locator( l.p_dvbs_locator );
     if( FAILED( hr ) )
     {
-        msg_Warn( p_access, "SubmitDVBCTuneRequest: "\
+        msg_Warn( p_access, "SubmitDVBSTuneRequest: "\
             "Cannot put the locator: hr=0x%8lx", hr );
         return VLC_EGENERIC;
     }
@@ -646,8 +739,14 @@ HRESULT BDAGraph::CreateTuneRequest()
         ITuningSpaceContainer*  p_tuning_space_container;
         IEnumTuningSpaces*      p_tuning_space_enum;
         ITuningSpace*           p_this_tuning_space;
+        BSTR                    bstr_name;
+        char * psz_network_name;
+        WCHAR * wpsz_network_name;
+        int i_name_len;
         localComPtr(): p_tuning_space_container(NULL),
-            p_tuning_space_enum(NULL), p_this_tuning_space(NULL) {};
+            p_tuning_space_enum(NULL), p_this_tuning_space(NULL),
+            i_name_len(0), psz_network_name(NULL), wpsz_network_name(NULL),
+            bstr_name(NULL) {};
         ~localComPtr()
         {
             if( p_tuning_space_container )
@@ -656,9 +755,32 @@ HRESULT BDAGraph::CreateTuneRequest()
                 p_tuning_space_enum->Release();
             if( p_this_tuning_space )
                 p_this_tuning_space->Release();
+            SysFreeString( bstr_name );
+            delete wpsz_network_name;
+            free(psz_network_name);
         }
     } l;
 
+    /* We shall test for a specific Tuning space name supplied on the command
+     * line as dvb-networkname=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 )
+    {
+        l.i_name_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+            l.psz_network_name, -1, l.wpsz_network_name, 0 );
+        if( l.i_name_len > 0 )
+        {
+            l.wpsz_network_name = new WCHAR[l.i_name_len];
+            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, l.psz_network_name, -1,
+                l.wpsz_network_name, l.i_name_len );
+            msg_Dbg( p_access, "CreateTuneRequest: Find Tuning Space: %S",
+                l.wpsz_network_name );
+        }
+    }
+
     /* A Tuning Space 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 */
@@ -668,13 +790,26 @@ HRESULT BDAGraph::CreateTuneRequest()
         if( FAILED( hr ) ) guid_this_network_type = GUID_NULL;
         if( guid_this_network_type == guid_network_type )
         {
-            return S_OK;
-        }
-        else
-        {
-            p_tuning_space->Release();
-            p_tuning_space = NULL;
+            hr = p_tuning_space->get_UniqueName( &l.bstr_name );
+            if( FAILED( hr ) )
+            {
+                msg_Warn( p_access, "CreateTuneRequest: "\
+                    "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
+                return hr;
+            }
+            /* Test for a specific Tuning space name supplied on the command
+             * line as dvb-networkname=xxx */
+            if( l.i_name_len == 0 ||
+                lstrcmpW( l.wpsz_network_name, l.bstr_name ) == 0 )
+            {
+                msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
+                    l.bstr_name );
+                return S_OK;
+            }
         }
+        /* else */
+        p_tuning_space->Release();
+        p_tuning_space = NULL;
     }
 
     /* Force use of the first available Tuner Device during Build */
@@ -703,7 +838,7 @@ HRESULT BDAGraph::CreateTuneRequest()
     while( l.p_tuning_space_enum->Next( 1, &l.p_this_tuning_space, NULL ) ==
         S_OK )
     {
-       hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
+        hr = l.p_this_tuning_space->get__NetworkType( &guid_this_network_type );
 
         /* GUID_NULL means a non-BDA network was found e.g analog
          * Ignore failures and non-BDA networks and keep looking */
@@ -719,23 +854,103 @@ HRESULT BDAGraph::CreateTuneRequest()
                     "Cannot QI Tuning Space: hr=0x%8lx", hr );
                 return hr;
             }
-            hr = p_tuning_space->CreateTuneRequest( &p_tune_request );
+            hr = p_tuning_space->get_UniqueName( &l.bstr_name );
             if( FAILED( hr ) )
             {
                 msg_Warn( p_access, "CreateTuneRequest: "\
-                    "Cannot Create Tune Request: hr=0x%8lx", hr );
+                    "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
+                return hr;
+            }
+
+            /* Test for a specific Tuning space name supplied on the command
+             * line as dvb-networkname=xxx */
+            if( l.i_name_len == 0 ||
+                lstrcmpW( l.wpsz_network_name, l.bstr_name ) == 0 )
+            {
+                msg_Dbg( p_access, "CreateTuneRequest: Using Tuning Space: %S",
+                    l.bstr_name );
+                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;
             }
-            return hr;
         }
     }
-    hr = E_FAIL;
-    if( FAILED( hr ) )
+    /* No tune request 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. */
+    free( l.psz_network_name );
+    l.psz_network_name = var_GetNonEmptyString( p_access, "dvb-create-name" );
+    if( !l.psz_network_name )
     {
+        hr = E_FAIL;
         msg_Warn( p_access, "CreateTuneRequest: "\
             "Cannot find a suitable System Tuning Space: hr=0x%8lx", hr );
         return hr;
     }
+
+    /* 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;
+
+    delete l.wpsz_network_name;
+    l.i_name_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+        l.psz_network_name, -1, l.wpsz_network_name, 0 );
+    if( l.i_name_len > 0 )
+    {
+        l.wpsz_network_name = new WCHAR[l.i_name_len];
+        MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, l.psz_network_name, -1,
+            l.wpsz_network_name, l.i_name_len );
+        if( l.bstr_name )
+            SysFreeString( l.bstr_name );
+        l.bstr_name = SysAllocString( l.wpsz_network_name );
+        msg_Dbg( p_access, "CreateTuneRequest: Create Tuning Space: %S",
+             l.bstr_name );
+    }
+    hr = ::CoCreateInstance( cls_tuning_space, 0, CLSCTX_INPROC,
+         IID_ITuningSpace, (void**)&p_tuning_space );
+    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 );
+    if( FAILED( hr ) )
+        msg_Warn( p_access, "CreateTuneRequest: "\
+            "Cannot Put Friendly Name: hr=0x%8lx", hr );
+    if( SUCCEEDED( hr ) )
+        hr = l.p_tuning_space_container->Add( p_tuning_space, &var_id );
+    if( FAILED( hr ) )
+    {
+        msg_Warn( p_access, "CreateTuneRequest: "\
+            "Cannot Create new TuningSpace: hr=0x%8lx", hr );
+        return hr;
+    }
+    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;
 }
 
@@ -748,7 +963,49 @@ HRESULT BDAGraph::Build()
 {
     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()
+        {
+            if( p_tuning_space_container )
+                p_tuning_space_container->Release();
+        }
+    } 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 %d",
+        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", hr );
+        return hr;
+    }
 
     /* If we have already have a filter graph, rebuild it*/
     Destroy();
@@ -961,7 +1218,7 @@ HRESULT BDAGraph::Build()
 * On subsequent calls, this can be used to start from that point to find
 * another match.
 * This is used when the graph does not run because a tuner device is in use so
-* another one needs to be slected.
+* another one needs to be selected.
 ******************************************************************************/
 HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
     IBaseFilter* p_upstream, IBaseFilter** p_p_downstream )
@@ -981,7 +1238,7 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
             p_moniker_enum(NULL),
             p_filter(NULL),
             p_property_bag(NULL)
-                { ::VariantInit(&var_bstr); };
+            { ::VariantInit(&var_bstr); };
         ~localComPtr()
         {
             if( p_moniker )
@@ -1000,16 +1257,16 @@ HRESULT BDAGraph::FindFilter( REFCLSID clsid, long* i_moniker_used,
     {
         hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
             IID_ICreateDevEnum, (void**)&p_system_dev_enum );
-         if( FAILED( hr ) )
-         {
-             msg_Warn( p_access, "FindFilter: "\
-                 "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
-             return hr;
+        if( FAILED( hr ) )
+        {
+            msg_Warn( p_access, "FindFilter: "\
+                "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
+            return hr;
         }
     }
 
     hr = p_system_dev_enum->CreateClassEnumerator( clsid,
-                                                   &l.p_moniker_enum, 0 );
+        &l.p_moniker_enum, 0 );
     if( hr != S_OK )
     {
         msg_Warn( p_access, "FindFilter: "\
@@ -1246,6 +1503,7 @@ HRESULT BDAGraph::Start()
         return hr;
 
     /* The Graph is not running so stop it and return an error */
+    msg_Warn( p_access, "Start: Graph not started: %d", i_state );
     hr = p_media_control->Stop();
     if( FAILED( hr ) )
     {
@@ -1261,15 +1519,23 @@ HRESULT BDAGraph::Start()
 *****************************************************************************/
 long BDAGraph::GetBufferSize()
 {
-    while( queue_sample.empty() )
-        Sleep( 50 );
-
     long l_buffer_size = 0;
     long l_queue_size;
 
+    b_ready = true;
+
+    for( int i_timer = 0; queue_sample.empty() && i_timer < 200; i_timer++ )
+        Sleep( 10 );
+
+    l_queue_size = queue_sample.size();
+    if( l_queue_size <= 0 )
+    {
+        msg_Warn( p_access, "BDA GetBufferSize: Timed Out waiting for sample" );
+        return -1;
+    }
+
     /* Establish the length of the queue as it grows quickly. If the queue
      * size is checked dynamically there is a risk of not exiting the loop */
-    l_queue_size = queue_sample.size();
     for( long l_queue_count=0; l_queue_count < l_queue_size; l_queue_count++ )
     {
         l_buffer_size += queue_sample.front()->GetActualDataLength();
@@ -1311,8 +1577,15 @@ long BDAGraph::ReadBuffer( long* pl_buffer_len, BYTE* p_buffer )
 ******************************************************************************/
 STDMETHODIMP BDAGraph::SampleCB( double d_time, IMediaSample *p_sample )
 {
-    p_sample->AddRef();
-    queue_sample.push( p_sample );
+    if( b_ready )
+    {
+        p_sample->AddRef();
+        queue_sample.push( p_sample );
+    }
+    else
+    {
+        msg_Warn( p_access, "BDA SampleCB: Not ready - dropped sample" );
+    }
     return S_OK;
 }
 
@@ -1379,7 +1652,7 @@ HRESULT BDAGraph::Destroy()
         p_media_control->Release();
         p_media_control = NULL;
     }
-    if( p_scanning_tuner )
+    if( p_filter_graph )
     {
         p_filter_graph->Release();
         p_filter_graph = NULL;
@@ -1426,17 +1699,28 @@ HRESULT BDAGraph::Register()
     wsprintfW( psz_w_graph_name, L"VLC BDA Graph %08x Pid %08x",
         (DWORD_PTR) p_filter_graph, ::GetCurrentProcessId() );
     hr = CreateItemMoniker( L"!", psz_w_graph_name, &l.p_moniker );
-    if( SUCCEEDED( hr ) )
-        hr = l.p_ro_table->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE,
-            p_filter_graph, l.p_moniker, &d_graph_register );
-
+    if( FAILED( hr ) )
+    {
+        msg_Warn( p_access, "Register: Cannot Create Moniker: hr=0x%8lx", hr );
+        return hr;
+    }
+    hr = l.p_ro_table->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE,
+        p_filter_graph, l.p_moniker, &d_graph_register );
+    if( FAILED( hr ) )
+    {
+        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 );
     return hr;
 }
 
 void BDAGraph::Deregister()
 {
+    HRESULT   hr;
     IRunningObjectTable* p_ro_table;
-    if( SUCCEEDED( ::GetRunningObjectTable( 0, &p_ro_table ) ) )
+    hr = ::GetRunningObjectTable( 0, &p_ro_table );
+    if( SUCCEEDED( hr ) )
         p_ro_table->Revoke( d_graph_register );
     d_graph_register = 0;
     p_ro_table->Release();