1 /*****************************************************************************
2 * bdagraph.cpp : DirectShow BDA graph for vlc
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
5 * Copyright (C) 2011 RĂ©mi Denis-Courmont
6 * Copyright (C) 2012 John Freed
8 * Author: Ken Self <kenself(at)optusnet(dot)com(dot)au>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_block.h>
34 #include "dtv/bdagraph.hpp"
36 #undef DEBUG_MONIKER_NAME
38 static ModulationType dvb_parse_modulation (const char *mod)
40 if (!strcmp (mod, "16QAM")) return BDA_MOD_16QAM;
41 if (!strcmp (mod, "32QAM")) return BDA_MOD_32QAM;
42 if (!strcmp (mod, "64QAM")) return BDA_MOD_64QAM;
43 if (!strcmp (mod, "128QAM")) return BDA_MOD_128QAM;
44 if (!strcmp (mod, "256QAM")) return BDA_MOD_256QAM;
45 return BDA_MOD_NOT_SET;
48 static BinaryConvolutionCodeRate dvb_parse_fec (uint32_t fec)
52 case VLC_FEC(1,2): return BDA_BCC_RATE_1_2;
53 case VLC_FEC(2,3): return BDA_BCC_RATE_2_3;
54 case VLC_FEC(3,4): return BDA_BCC_RATE_3_4;
55 case VLC_FEC(5,6): return BDA_BCC_RATE_5_6;
56 case VLC_FEC(7,8): return BDA_BCC_RATE_7_8;
58 return BDA_BCC_RATE_NOT_SET;
61 static GuardInterval dvb_parse_guard (uint32_t guard)
65 case VLC_GUARD(1, 4): return BDA_GUARD_1_4;
66 case VLC_GUARD(1, 8): return BDA_GUARD_1_8;
67 case VLC_GUARD(1,16): return BDA_GUARD_1_16;
68 case VLC_GUARD(1,32): return BDA_GUARD_1_32;
70 return BDA_GUARD_NOT_SET;
73 static TransmissionMode dvb_parse_transmission (int transmit)
77 case 2: return BDA_XMIT_MODE_2K;
78 case 8: return BDA_XMIT_MODE_8K;
80 return BDA_XMIT_MODE_NOT_SET;
83 static HierarchyAlpha dvb_parse_hierarchy (int hierarchy)
87 case 1: return BDA_HALPHA_1;
88 case 2: return BDA_HALPHA_2;
89 case 4: return BDA_HALPHA_4;
91 return BDA_HALPHA_NOT_SET;
94 static Polarisation dvb_parse_polarization (char pol)
98 case 'H': return BDA_POLARISATION_LINEAR_H;
99 case 'V': return BDA_POLARISATION_LINEAR_V;
100 case 'L': return BDA_POLARISATION_CIRCULAR_L;
101 case 'R': return BDA_POLARISATION_CIRCULAR_R;
103 return BDA_POLARISATION_NOT_SET;
106 static SpectralInversion dvb_parse_inversion (int inversion)
110 case 0: return BDA_SPECTRAL_INVERSION_NORMAL;
111 case 1: return BDA_SPECTRAL_INVERSION_INVERTED;
112 case -1: return BDA_SPECTRAL_INVERSION_AUTOMATIC;
114 /* should never happen */
115 return BDA_SPECTRAL_INVERSION_NOT_SET;
118 /****************************************************************************
119 * Interfaces for calls from C
120 ****************************************************************************/
125 /* DVB-S property cache */
131 uint32_t lowf, highf, switchf;
134 dvb_device_t *dvb_open (vlc_object_t *obj)
136 dvb_device_t *d = new dvb_device_t;
138 d->module = new BDAGraph (obj);
141 d->fec = VLC_FEC_AUTO;
144 d->lowf = d->highf = d->switchf = 0;
148 void dvb_close (dvb_device_t *d)
154 ssize_t dvb_read (dvb_device_t *d, void *buf, size_t len)
156 return d->module->Pop(buf, len);
159 int dvb_add_pid (dvb_device_t *, uint16_t)
164 void dvb_remove_pid (dvb_device_t *, uint16_t)
168 unsigned dvb_enum_systems (dvb_device_t *d)
170 return d->module->EnumSystems( );
173 float dvb_get_signal_strength (dvb_device_t *d)
175 return d->module->GetSignalStrength( );
178 float dvb_get_snr (dvb_device_t *d)
180 return d->module->GetSignalNoiseRatio( );
183 int dvb_set_inversion (dvb_device_t *d, int inversion)
185 d->inversion = inversion;
186 return d->module->SetInversion( d->inversion );
189 int dvb_tune (dvb_device_t *d)
191 return d->module->SubmitTuneRequest ();
195 int dvb_set_dvbc (dvb_device_t *d, uint32_t freq, const char *mod,
196 uint32_t srate, uint32_t /*fec*/)
198 return d->module->SetDVBC (freq / 1000, mod, srate);
202 int dvb_set_dvbs (dvb_device_t *d, uint64_t freq, uint32_t srate, uint32_t fec)
204 d->frequency = freq / 1000;
207 return d->module->SetDVBS(d->frequency, d->srate, d->fec, d->inversion,
208 d->pol, d->lowf, d->highf, d->switchf);
211 int dvb_set_dvbs2 (dvb_device_t *, uint64_t /*freq*/, const char * /*mod*/,
212 uint32_t /*srate*/, uint32_t /*fec*/, int /*pilot*/, int /*rolloff*/)
217 int dvb_set_sec (dvb_device_t *d, uint64_t freq, char pol,
218 uint32_t lowf, uint32_t highf, uint32_t switchf)
220 d->frequency = freq / 1000;
224 d->switchf = switchf;
225 return d->module->SetDVBS(d->frequency, d->srate, d->fec, d->inversion,
226 d->pol, d->lowf, d->highf, d->switchf);
230 int dvb_set_dvbt (dvb_device_t *d, uint32_t freq, const char * /*mod*/,
231 uint32_t fec_hp, uint32_t fec_lp, uint32_t bandwidth,
232 int transmission, uint32_t guard, int hierarchy)
234 return d->module->SetDVBT(freq / 1000, fec_hp, fec_lp,
235 bandwidth, transmission, guard, hierarchy);
238 int dvb_set_dvbt2 (dvb_device_t *, uint32_t /*freq*/, const char * /*mod*/,
239 uint32_t /*fec*/, uint32_t /*bandwidth*/, int /*tx_mode*/,
240 uint32_t /*guard*/, uint32_t /*plp*/)
246 int dvb_set_isdbc (dvb_device_t *, uint32_t /*freq*/, const char * /*mod*/,
247 uint32_t /*srate*/, uint32_t /*fec*/)
253 int dvb_set_isdbs (dvb_device_t *, uint64_t /*freq*/, uint16_t /*ts_id*/)
259 int dvb_set_isdbt (dvb_device_t *, uint32_t /*freq*/, uint32_t /*bandwidth*/,
260 int /*transmit_mode*/, uint32_t /*guard*/,
261 const isdbt_layer_t /*layers*/[3])
267 int dvb_set_atsc (dvb_device_t *d, uint32_t freq, const char * /*mod*/)
269 return d->module->SetATSC(freq / 1000);
272 int dvb_set_cqam (dvb_device_t *d, uint32_t freq, const char * /*mod*/)
274 return d->module->SetCQAM(freq / 1000);
277 /*****************************************************************************
279 *****************************************************************************/
280 BDAOutput::BDAOutput( vlc_object_t *p_access ) :
281 p_access(p_access), p_first(NULL), pp_next(&p_first)
283 vlc_mutex_init( &lock );
284 vlc_cond_init( &wait );
287 BDAOutput::~BDAOutput()
290 vlc_mutex_destroy( &lock );
291 vlc_cond_destroy( &wait );
294 void BDAOutput::Push( block_t *p_block )
296 vlc_mutex_locker l( &lock );
298 block_ChainLastAppend( &pp_next, p_block );
299 vlc_cond_signal( &wait );
302 ssize_t BDAOutput::Pop(void *buf, size_t len)
304 vlc_mutex_locker l( &lock );
306 mtime_t i_deadline = mdate() + 250 * 1000;
309 if( vlc_cond_timedwait( &wait, &lock, i_deadline ) )
314 while( i_index < len )
316 size_t i_copy = __MIN( len - i_index, p_first->i_buffer );
317 memcpy( (uint8_t *)buf + i_index, p_first->p_buffer, i_copy );
321 p_first->p_buffer += i_copy;
322 p_first->i_buffer -= i_copy;
324 if( p_first->i_buffer <= 0 )
326 block_t *p_next = p_first->p_next;
327 block_Release( p_first );
340 void BDAOutput::Empty()
342 vlc_mutex_locker l( &lock );
345 block_ChainRelease( p_first );
350 /*****************************************************************************
352 *****************************************************************************/
353 BDAGraph::BDAGraph( vlc_object_t *p_this ):
355 guid_network_type(GUID_NULL),
358 d_graph_register( 0 ),
361 p_media_control = NULL;
363 p_tuning_space = NULL;
365 p_filter_graph = NULL;
366 p_system_dev_enum = NULL;
367 p_network_provider = p_tuner_device = p_capture_device = NULL;
368 p_sample_grabber = p_mpeg_demux = p_transport_info = NULL;
369 p_scanning_tuner = NULL;
372 CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
375 /*****************************************************************************
377 *****************************************************************************/
378 BDAGraph::~BDAGraph()
383 p_tuning_space->Release();
384 p_tuning_space = NULL;
390 /*****************************************************************************
393 *****************************************************************************/
394 unsigned BDAGraph::GetSystem( REFCLSID clsid )
398 if( clsid == CLSID_DVBTNetworkProvider )
400 if( clsid == CLSID_DVBCNetworkProvider )
402 if( clsid == CLSID_DVBSNetworkProvider )
404 if( clsid == CLSID_ATSCNetworkProvider )
406 if( clsid == CLSID_DigitalCableNetworkType )
413 /*****************************************************************************
415 *****************************************************************************
416 * here is logic for special case where user uses an MRL that points
417 * to DTV but is not fully specific. This is usually dvb:// and can come
418 * either from a playlist, a channels.conf MythTV file, or from manual entry.
420 * Since this is done before the real tune request is submitted, we can
421 * use the global device enumerator, etc., so long as we do a Destroy() at
423 *****************************************************************************/
424 unsigned BDAGraph::EnumSystems()
427 GUID guid_network_provider = GUID_NULL;
429 msg_Dbg( p_access, "EnumSystems: Entering " );
433 hr = GetNextNetworkType( &guid_network_provider );
434 if( hr != S_OK ) break;
435 hr = Check( guid_network_provider );
437 msg_Dbg( p_access, "EnumSystems: Check failed, trying next" );
443 msg_Dbg( p_access, "EnumSystems: Returning systems 0x%08x", systems );
447 float BDAGraph::GetSignalNoiseRatio(void)
449 /* not implemented until Windows 7
450 * IBDA_Encoder::GetState */
454 float BDAGraph::GetSignalStrength(void)
458 msg_Dbg( p_access, "GetSignalStrength: entering" );
459 if( !p_scanning_tuner)
461 hr = p_scanning_tuner->get_SignalStrength( &l_strength );
464 msg_Warn( p_access, "GetSignalStrength: "
465 "Cannot get value: hr=0x%8lx", hr );
468 msg_Dbg( p_access, "GetSignalStrength: got %ld", l_strength );
469 if( l_strength == -1 )
471 return l_strength / 100.;
474 int BDAGraph::SubmitTuneRequest(void)
479 /* Build and Start the Graph. If a Tuner device is in use the graph will
480 * fail to start. Repeated calls to Build will check successive tuner
484 msg_Dbg( p_access, "SubmitTuneRequest: Building the Graph" );
489 msg_Warn( p_access, "SubmitTuneRequest: "
490 "Cannot Build the Graph: hr=0x%8lx", hr );
493 msg_Dbg( p_access, "SubmitTuneRequest: Starting the Graph" );
498 msg_Dbg( p_access, "SubmitTuneRequest: "
499 "Cannot Start the Graph, retrying: hr=0x%8lx", hr );
503 while( hr != S_OK && i < 10 ); /* give up after 10 tries */
507 msg_Warn( p_access, "SubmitTuneRequest: "
508 "Failed to Start the Graph: hr=0x%8lx", hr );
515 /*****************************************************************************
516 * Set Clear QAM (DigitalCable)
517 * Local ATSC Digital Antenna
518 *****************************************************************************/
519 int BDAGraph::SetCQAM(long l_frequency)
525 ITuneRequest* p_tune_request;
526 IDigitalCableTuneRequest* p_cqam_tune_request;
527 IDigitalCableLocator* p_cqam_locator;
529 p_tune_request(NULL),
530 p_cqam_tune_request(NULL),
536 p_tune_request->Release();
537 if( p_cqam_tune_request )
538 p_cqam_tune_request->Release();
540 p_cqam_locator->Release();
543 long l_minor_channel, l_physical_channel;
545 l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
546 l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
548 /* try to set p_scanning_tuner */
549 hr = Check( CLSID_DigitalCableNetworkType );
552 msg_Warn( p_access, "SetCQAM: "\
553 "Cannot create Tuning Space: hr=0x%8lx", hr );
557 if( !p_scanning_tuner )
559 msg_Warn( p_access, "SetCQAM: Cannot get scanning tuner" );
563 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
566 msg_Warn( p_access, "SetCQAM: "\
567 "Cannot get Tune Request: hr=0x%8lx", hr );
571 hr = l.p_tune_request->QueryInterface( IID_IDigitalCableTuneRequest,
572 reinterpret_cast<void**>( &l.p_cqam_tune_request ) );
575 msg_Warn( p_access, "SetCQAM: "\
576 "Cannot QI for IDigitalCableTuneRequest: hr=0x%8lx", hr );
580 hr = ::CoCreateInstance( CLSID_DigitalCableLocator, 0, CLSCTX_INPROC,
581 IID_IDigitalCableLocator, reinterpret_cast<void**>( &l.p_cqam_locator ) );
584 msg_Warn( p_access, "SetCQAM: "\
585 "Cannot create the CQAM locator: hr=0x%8lx", hr );
590 if( SUCCEEDED( hr ) && l_physical_channel > 0 )
591 hr = l.p_cqam_locator->put_PhysicalChannel( l_physical_channel );
592 if( SUCCEEDED( hr ) && l_frequency > 0 )
593 hr = l.p_cqam_locator->put_CarrierFrequency( l_frequency );
594 if( SUCCEEDED( hr ) && l_minor_channel > 0 )
595 hr = l.p_cqam_tune_request->put_MinorChannel( l_minor_channel );
598 msg_Warn( p_access, "SetCQAM: "\
599 "Cannot set tuning parameters: hr=0x%8lx", hr );
603 hr = l.p_cqam_tune_request->put_Locator( l.p_cqam_locator );
606 msg_Warn( p_access, "SetCQAM: "\
607 "Cannot put the locator: hr=0x%8lx", hr );
611 hr = p_scanning_tuner->Validate( l.p_cqam_tune_request );
614 msg_Dbg( p_access, "SetCQAM: "\
615 "Tune Request cannot be validated: hr=0x%8lx", hr );
617 /* increments ref count for scanning tuner */
618 hr = p_scanning_tuner->put_TuneRequest( l.p_cqam_tune_request );
621 msg_Warn( p_access, "SetCQAM: "\
622 "Cannot put the tune request: hr=0x%8lx", hr );
629 /*****************************************************************************
631 *****************************************************************************/
632 int BDAGraph::SetATSC(long l_frequency)
638 ITuneRequest* p_tune_request;
639 IATSCChannelTuneRequest* p_atsc_tune_request;
640 IATSCLocator* p_atsc_locator;
642 p_tune_request(NULL),
643 p_atsc_tune_request(NULL),
649 p_tune_request->Release();
650 if( p_atsc_tune_request )
651 p_atsc_tune_request->Release();
653 p_atsc_locator->Release();
656 long l_major_channel, l_minor_channel, l_physical_channel;
658 /* fixme: these parameters should have dtv prefix, not dvb */
659 l_major_channel = var_GetInteger( p_access, "dvb-major-channel" );
660 l_minor_channel = var_GetInteger( p_access, "dvb-minor-channel" );
661 l_physical_channel = var_GetInteger( p_access, "dvb-physical-channel" );
663 /* try to set p_scanning_tuner */
664 hr = Check( CLSID_ATSCNetworkProvider );
667 msg_Warn( p_access, "SetATSC: "\
668 "Cannot create Tuning Space: hr=0x%8lx", hr );
672 if( !p_scanning_tuner )
674 msg_Warn( p_access, "SetATSC: Cannot get scanning tuner" );
678 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
681 msg_Warn( p_access, "SetATSC: "\
682 "Cannot get Tune Request: hr=0x%8lx", hr );
686 hr = l.p_tune_request->QueryInterface( IID_IATSCChannelTuneRequest,
687 reinterpret_cast<void**>( &l.p_atsc_tune_request ) );
690 msg_Warn( p_access, "SetATSC: "\
691 "Cannot QI for IATSCChannelTuneRequest: hr=0x%8lx", hr );
695 hr = ::CoCreateInstance( CLSID_ATSCLocator, 0, CLSCTX_INPROC,
696 IID_IATSCLocator, reinterpret_cast<void**>( &l.p_atsc_locator ) );
699 msg_Warn( p_access, "SetATSC: "\
700 "Cannot create the ATSC locator: hr=0x%8lx", hr );
705 if( l_frequency > 0 )
706 hr = l.p_atsc_locator->put_CarrierFrequency( l_frequency );
707 if( l_major_channel > 0 )
708 hr = l.p_atsc_tune_request->put_Channel( l_major_channel );
709 if( SUCCEEDED( hr ) && l_minor_channel > 0 )
710 hr = l.p_atsc_tune_request->put_MinorChannel( l_minor_channel );
711 if( SUCCEEDED( hr ) && l_physical_channel > 0 )
712 hr = l.p_atsc_locator->put_PhysicalChannel( l_physical_channel );
715 msg_Warn( p_access, "SetATSC: "\
716 "Cannot set tuning parameters: hr=0x%8lx", hr );
720 hr = l.p_atsc_tune_request->put_Locator( l.p_atsc_locator );
723 msg_Warn( p_access, "SetATSC: "\
724 "Cannot put the locator: hr=0x%8lx", hr );
728 hr = p_scanning_tuner->Validate( l.p_atsc_tune_request );
731 msg_Dbg( p_access, "SetATSC: "\
732 "Tune Request cannot be validated: hr=0x%8lx", hr );
734 /* increments ref count for scanning tuner */
735 hr = p_scanning_tuner->put_TuneRequest( l.p_atsc_tune_request );
738 msg_Warn( p_access, "SetATSC: "\
739 "Cannot put the tune request: hr=0x%8lx", hr );
746 /*****************************************************************************
749 * This provides the tune request that everything else is built upon.
751 * Stores the tune request to the scanning tuner, where it is pulled out by
752 * dvb_tune a/k/a SubmitTuneRequest.
753 ******************************************************************************/
754 int BDAGraph::SetDVBT(long l_frequency, uint32_t fec_hp, uint32_t fec_lp,
755 long l_bandwidth, int transmission, uint32_t guard, int hierarchy)
762 ITuneRequest* p_tune_request;
763 IDVBTuneRequest* p_dvb_tune_request;
764 IDVBTLocator* p_dvbt_locator;
765 IDVBTuningSpace2* p_dvb_tuning_space;
767 p_tune_request(NULL),
768 p_dvb_tune_request(NULL),
769 p_dvbt_locator(NULL),
770 p_dvb_tuning_space(NULL)
775 p_tune_request->Release();
776 if( p_dvb_tune_request )
777 p_dvb_tune_request->Release();
779 p_dvbt_locator->Release();
780 if( p_dvb_tuning_space )
781 p_dvb_tuning_space->Release();
785 /* create local dvbt-specific tune request and locator
786 * then put it to existing scanning tuner */
787 BinaryConvolutionCodeRate i_hp_fec = dvb_parse_fec(fec_hp);
788 BinaryConvolutionCodeRate i_lp_fec = dvb_parse_fec(fec_lp);
789 GuardInterval i_guard = dvb_parse_guard(guard);
790 TransmissionMode i_transmission = dvb_parse_transmission(transmission);
791 HierarchyAlpha i_hierarchy = dvb_parse_hierarchy(hierarchy);
793 /* try to set p_scanning_tuner */
794 msg_Dbg( p_access, "SetDVBT: set up scanning tuner" );
795 hr = Check( CLSID_DVBTNetworkProvider );
798 msg_Warn( p_access, "SetDVBT: "\
799 "Cannot create Tuning Space: hr=0x%8lx", hr );
803 if( !p_scanning_tuner )
805 msg_Warn( p_access, "SetDVBT: Cannot get scanning tuner" );
809 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
812 msg_Warn( p_access, "SetDVBT: "\
813 "Cannot get Tune Request: hr=0x%8lx", hr );
817 msg_Dbg( p_access, "SetDVBT: Creating DVB tune request" );
818 hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
819 reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
822 msg_Warn( p_access, "SetDVBT: "\
823 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
827 l.p_dvb_tune_request->put_ONID( -1 );
828 l.p_dvb_tune_request->put_SID( -1 );
829 l.p_dvb_tune_request->put_TSID( -1 );
831 msg_Dbg( p_access, "SetDVBT: get TS" );
832 hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
835 msg_Dbg( p_access, "SetDVBT: "\
836 "cannot get tuning space: hr=0x%8lx", hr );
840 msg_Dbg( p_access, "SetDVBT: QI to DVBT TS" );
841 hr = p_tuning_space->QueryInterface( IID_IDVBTuningSpace2,
842 reinterpret_cast<void**>( &l.p_dvb_tuning_space ) );
845 msg_Warn( p_access, "SetDVBT: "\
846 "Cannot QI for IDVBTuningSpace2: hr=0x%8lx", hr );
850 msg_Dbg( p_access, "SetDVBT: Creating local locator" );
851 hr = ::CoCreateInstance( CLSID_DVBTLocator, 0, CLSCTX_INPROC,
852 IID_IDVBTLocator, reinterpret_cast<void**>( &l.p_dvbt_locator ) );
855 msg_Warn( p_access, "SetDVBT: "\
856 "Cannot create the DVBT Locator: hr=0x%8lx", hr );
860 hr = l.p_dvb_tuning_space->put_SystemType( DVB_Terrestrial );
861 if( SUCCEEDED( hr ) && l_frequency > 0 )
862 hr = l.p_dvbt_locator->put_CarrierFrequency( l_frequency );
863 if( SUCCEEDED( hr ) && l_bandwidth > 0 )
864 hr = l.p_dvbt_locator->put_Bandwidth( l_bandwidth );
865 if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
866 hr = l.p_dvbt_locator->put_InnerFECRate( i_hp_fec );
867 if( SUCCEEDED( hr ) && i_lp_fec != BDA_BCC_RATE_NOT_SET )
868 hr = l.p_dvbt_locator->put_LPInnerFECRate( i_lp_fec );
869 if( SUCCEEDED( hr ) && i_guard != BDA_GUARD_NOT_SET )
870 hr = l.p_dvbt_locator->put_Guard( i_guard );
871 if( SUCCEEDED( hr ) && i_transmission != BDA_XMIT_MODE_NOT_SET )
872 hr = l.p_dvbt_locator->put_Mode( i_transmission );
873 if( SUCCEEDED( hr ) && i_hierarchy != BDA_HALPHA_NOT_SET )
874 hr = l.p_dvbt_locator->put_HAlpha( i_hierarchy );
878 msg_Warn( p_access, "SetDVBT: "\
879 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
883 msg_Dbg( p_access, "SetDVBT: putting DVBT locator into local tune request" );
885 hr = l.p_dvb_tune_request->put_Locator( l.p_dvbt_locator );
888 msg_Warn( p_access, "SetDVBT: "\
889 "Cannot put the locator: hr=0x%8lx", hr );
893 msg_Dbg( p_access, "SetDVBT: putting local Tune Request to scanning tuner" );
894 hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
897 msg_Dbg( p_access, "SetDVBT: "\
898 "Tune Request cannot be validated: hr=0x%8lx", hr );
900 /* increments ref count for scanning tuner */
901 hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
904 msg_Warn( p_access, "SetDVBT: "\
905 "Cannot put the tune request: hr=0x%8lx", hr );
909 msg_Dbg( p_access, "SetDVBT: return success" );
913 /*****************************************************************************
915 ******************************************************************************/
916 int BDAGraph::SetDVBC(long l_frequency, const char *mod, long l_symbolrate)
923 ITuneRequest* p_tune_request;
924 IDVBTuneRequest* p_dvb_tune_request;
925 IDVBCLocator* p_dvbc_locator;
926 IDVBTuningSpace2* p_dvb_tuning_space;
929 p_tune_request(NULL),
930 p_dvb_tune_request(NULL),
931 p_dvbc_locator(NULL),
932 p_dvb_tuning_space(NULL)
937 p_tune_request->Release();
938 if( p_dvb_tune_request )
939 p_dvb_tune_request->Release();
941 p_dvbc_locator->Release();
942 if( p_dvb_tuning_space )
943 p_dvb_tuning_space->Release();
947 ModulationType i_qam_mod = dvb_parse_modulation(mod);
949 /* try to set p_scanning_tuner */
950 hr = Check( CLSID_DVBCNetworkProvider );
951 msg_Dbg( p_access, "SetDVBC: returned from Check" );
955 msg_Warn( p_access, "SetDVBC: "\
956 "Cannot create Tuning Space: hr=0x%8lx", hr );
960 msg_Dbg( p_access, "SetDVBC: check on scanning tuner" );
961 if( !p_scanning_tuner )
963 msg_Warn( p_access, "SetDVBC: Cannot get scanning tuner" );
967 msg_Dbg( p_access, "SetDVBC: get tune request" );
968 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
971 msg_Warn( p_access, "SetDVBC: "\
972 "Cannot get Tune Request: hr=0x%8lx", hr );
976 msg_Dbg( p_access, "SetDVBC: QI for dvb tune request" );
977 hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
978 reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
981 msg_Warn( p_access, "SetDVBC: "\
982 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
986 l.p_dvb_tune_request->put_ONID( -1 );
987 l.p_dvb_tune_request->put_SID( -1 );
988 l.p_dvb_tune_request->put_TSID( -1 );
990 msg_Dbg( p_access, "SetDVBC: create dvbc locator" );
991 hr = ::CoCreateInstance( CLSID_DVBCLocator, 0, CLSCTX_INPROC,
992 IID_IDVBCLocator, reinterpret_cast<void**>( &l.p_dvbc_locator ) );
995 msg_Warn( p_access, "SetDVBC: "\
996 "Cannot create the DVB-C Locator: hr=0x%8lx", hr );
1001 msg_Dbg( p_access, "SetDVBC: get TS" );
1002 hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
1005 msg_Dbg( p_access, "SetDVBC: "\
1006 "cannot get tuning space: hr=0x%8lx", hr );
1007 return VLC_EGENERIC;
1010 msg_Dbg( p_access, "SetDVBC: QI for dvb tuning space" );
1011 hr = p_tuning_space->QueryInterface( IID_IDVBTuningSpace2,
1012 reinterpret_cast<void**>( &l.p_dvb_tuning_space ) );
1015 msg_Warn( p_access, "SetDVBC: "\
1016 "Cannot QI for IDVBTuningSpace2: hr=0x%8lx", hr );
1017 return VLC_EGENERIC;
1020 msg_Dbg( p_access, "SetDVBC: set up locator" );
1022 hr = l.p_dvb_tuning_space->put_SystemType( DVB_Cable );
1024 if( SUCCEEDED( hr ) && l_frequency > 0 )
1025 hr = l.p_dvbc_locator->put_CarrierFrequency( l_frequency );
1026 if( SUCCEEDED( hr ) && l_symbolrate > 0 )
1027 hr = l.p_dvbc_locator->put_SymbolRate( l_symbolrate );
1028 if( SUCCEEDED( hr ) && i_qam_mod != BDA_MOD_NOT_SET )
1029 hr = l.p_dvbc_locator->put_Modulation( i_qam_mod );
1033 msg_Warn( p_access, "SetDVBC: "\
1034 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
1035 return VLC_EGENERIC;
1038 msg_Dbg( p_access, "SetDVBC: put locator to dvb tune request" );
1039 hr = l.p_dvb_tune_request->put_Locator( l.p_dvbc_locator );
1042 msg_Warn( p_access, "SetDVBC: "\
1043 "Cannot put the locator: hr=0x%8lx", hr );
1044 return VLC_EGENERIC;
1047 msg_Dbg( p_access, "SetDVBC: validate dvb tune request" );
1048 hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
1051 msg_Dbg( p_access, "SetDVBC: "\
1052 "Tune Request cannot be validated: hr=0x%8lx", hr );
1055 /* increments ref count for scanning tuner */
1056 msg_Dbg( p_access, "SetDVBC: put dvb tune request to tuner" );
1057 hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
1060 msg_Warn( p_access, "SetDVBC: "\
1061 "Cannot put the tune request: hr=0x%8lx", hr );
1062 return VLC_EGENERIC;
1064 msg_Dbg( p_access, "SetDVBC: return success" );
1069 /*****************************************************************************
1071 ******************************************************************************/
1072 int BDAGraph::SetInversion(int inversion)
1078 IDVBSTuningSpace* p_dvbs_tuning_space;
1080 p_dvbs_tuning_space(NULL)
1084 if( p_dvbs_tuning_space )
1085 p_dvbs_tuning_space->Release();
1089 SpectralInversion i_inversion = dvb_parse_inversion( inversion );
1091 if( !p_scanning_tuner )
1093 msg_Warn( p_access, "SetInversion: "\
1094 "No scanning tuner" );
1095 return VLC_EGENERIC;
1098 /* SetInversion is called for all DVB tuners, before the dvb_tune(),
1099 * in access.c. Since DVBT and DVBC don't support spectral
1100 * inversion, we need to return VLC_SUCCESS in those cases
1101 * so that dvb_tune() will be called */
1102 if( ( GetSystem( guid_network_type ) & ( DVB_S | DVB_S2 | ISDB_S ) ) == 0 )
1104 msg_Dbg( p_access, "SetInversion: Not Satellite type" );
1108 msg_Dbg( p_access, "SetInversion: get TS" );
1109 hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
1112 msg_Warn( p_access, "SetInversion: "\
1113 "cannot get tuning space: hr=0x%8lx", hr );
1114 return VLC_EGENERIC;
1117 hr = p_tuning_space->QueryInterface( IID_IDVBSTuningSpace,
1118 reinterpret_cast<void**>( &l.p_dvbs_tuning_space ) );
1121 msg_Warn( p_access, "SetInversion: "\
1122 "Cannot QI for IDVBSTuningSpace: hr=0x%8lx", hr );
1123 return VLC_EGENERIC;
1126 if( i_inversion != BDA_SPECTRAL_INVERSION_NOT_SET )
1127 hr = l.p_dvbs_tuning_space->put_SpectralInversion( i_inversion );
1130 msg_Warn( p_access, "SetInversion: "\
1131 "Cannot put inversion: hr=0x%8lx", hr );
1132 return VLC_EGENERIC;
1138 /*****************************************************************************
1140 ******************************************************************************/
1141 int BDAGraph::SetDVBS(long l_frequency, long l_symbolrate, uint32_t fec,
1142 int inversion, char pol,
1143 long l_lnb_lof1, long l_lnb_lof2, long l_lnb_slof)
1150 ITuneRequest* p_tune_request;
1151 IDVBTuneRequest* p_dvb_tune_request;
1152 IDVBSLocator* p_dvbs_locator;
1153 IDVBSTuningSpace* p_dvbs_tuning_space;
1154 char* psz_polarisation;
1155 char* psz_input_range;
1156 BSTR bstr_input_range;
1157 WCHAR* pwsz_input_range;
1160 p_tune_request(NULL),
1161 p_dvb_tune_request(NULL),
1162 p_dvbs_locator(NULL),
1163 p_dvbs_tuning_space(NULL),
1164 psz_polarisation(NULL),
1165 psz_input_range(NULL),
1166 bstr_input_range(NULL),
1167 pwsz_input_range(NULL),
1172 if( p_tune_request )
1173 p_tune_request->Release();
1174 if( p_dvb_tune_request )
1175 p_dvb_tune_request->Release();
1176 if( p_dvbs_locator )
1177 p_dvbs_locator->Release();
1178 if( p_dvbs_tuning_space )
1179 p_dvbs_tuning_space->Release();
1180 SysFreeString( bstr_input_range );
1181 if( pwsz_input_range )
1182 delete[] pwsz_input_range;
1183 free( psz_input_range );
1184 free( psz_polarisation );
1187 long l_azimuth, l_elevation, l_longitude;
1189 VARIANT_BOOL b_west;
1191 BinaryConvolutionCodeRate i_hp_fec = dvb_parse_fec( fec );
1192 Polarisation i_polar = dvb_parse_polarization( pol );
1193 SpectralInversion i_inversion = dvb_parse_inversion( inversion );
1195 l_azimuth = var_GetInteger( p_access, "dvb-azimuth" );
1196 l_elevation = var_GetInteger( p_access, "dvb-elevation" );
1197 l_longitude = var_GetInteger( p_access, "dvb-longitude" );
1198 l_network_id = var_GetInteger( p_access, "dvb-network-id" );
1200 if( asprintf( &l.psz_polarisation, "%c", pol ) == -1 )
1203 b_west = ( l_longitude < 0 );
1205 l.psz_input_range = var_GetNonEmptyString( p_access, "dvb-range" );
1206 l.i_range_len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
1207 l.psz_input_range, -1, l.pwsz_input_range, 0 );
1208 if( l.i_range_len > 0 )
1210 l.pwsz_input_range = new WCHAR[l.i_range_len];
1211 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
1212 l.psz_input_range, -1, l.pwsz_input_range, l.i_range_len );
1213 l.bstr_input_range = SysAllocString( l.pwsz_input_range );
1216 /* try to set p_scanning_tuner */
1217 hr = Check( CLSID_DVBSNetworkProvider );
1220 msg_Warn( p_access, "SetDVBS: "\
1221 "Cannot create Tuning Space: hr=0x%8lx", hr );
1222 return VLC_EGENERIC;
1225 if( !p_scanning_tuner )
1227 msg_Warn( p_access, "SetDVBS: Cannot get scanning tuner" );
1228 return VLC_EGENERIC;
1231 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
1234 msg_Warn( p_access, "SetDVBS: "\
1235 "Cannot get Tune Request: hr=0x%8lx", hr );
1236 return VLC_EGENERIC;
1239 hr = l.p_tune_request->QueryInterface( IID_IDVBTuneRequest,
1240 reinterpret_cast<void**>( &l.p_dvb_tune_request ) );
1243 msg_Warn( p_access, "SetDVBS: "\
1244 "Cannot QI for IDVBTuneRequest: hr=0x%8lx", hr );
1245 return VLC_EGENERIC;
1248 l.p_dvb_tune_request->put_ONID( -1 );
1249 l.p_dvb_tune_request->put_SID( -1 );
1250 l.p_dvb_tune_request->put_TSID( -1 );
1252 hr = ::CoCreateInstance( CLSID_DVBSLocator, 0, CLSCTX_INPROC,
1253 IID_IDVBSLocator, reinterpret_cast<void**>( &l.p_dvbs_locator ) );
1256 msg_Warn( p_access, "SetDVBS: "\
1257 "Cannot create the DVBS Locator: hr=0x%8lx", hr );
1258 return VLC_EGENERIC;
1261 msg_Dbg( p_access, "SetDVBS: get TS" );
1262 hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
1265 msg_Dbg( p_access, "SetDVBS: "\
1266 "cannot get tuning space: hr=0x%8lx", hr );
1267 return VLC_EGENERIC;
1270 hr = p_tuning_space->QueryInterface( IID_IDVBSTuningSpace,
1271 reinterpret_cast<void**>( &l.p_dvbs_tuning_space ) );
1274 msg_Warn( p_access, "SetDVBS: "\
1275 "Cannot QI for IDVBSTuningSpace: hr=0x%8lx", hr );
1276 return VLC_EGENERIC;
1279 hr = l.p_dvbs_tuning_space->put_SystemType( DVB_Satellite );
1280 if( SUCCEEDED( hr ) && l_lnb_lof1 > 0 )
1281 hr = l.p_dvbs_tuning_space->put_LowOscillator( l_lnb_lof1 );
1282 if( SUCCEEDED( hr ) && l_lnb_slof > 0 )
1283 hr = l.p_dvbs_tuning_space->put_LNBSwitch( l_lnb_slof );
1284 if( SUCCEEDED( hr ) && l_lnb_lof2 > 0 )
1285 hr = l.p_dvbs_tuning_space->put_HighOscillator( l_lnb_lof2 );
1286 if( SUCCEEDED( hr ) && i_inversion != BDA_SPECTRAL_INVERSION_NOT_SET )
1287 hr = l.p_dvbs_tuning_space->put_SpectralInversion( i_inversion );
1288 if( SUCCEEDED( hr ) && l_network_id > 0 )
1289 hr = l.p_dvbs_tuning_space->put_NetworkID( l_network_id );
1290 if( SUCCEEDED( hr ) && l.i_range_len > 0 )
1291 hr = l.p_dvbs_tuning_space->put_InputRange( l.bstr_input_range );
1293 if( SUCCEEDED( hr ) && l_frequency > 0 )
1294 hr = l.p_dvbs_locator->put_CarrierFrequency( l_frequency );
1295 if( SUCCEEDED( hr ) && l_symbolrate > 0 )
1296 hr = l.p_dvbs_locator->put_SymbolRate( l_symbolrate );
1297 if( SUCCEEDED( hr ) && i_polar != BDA_POLARISATION_NOT_SET )
1298 hr = l.p_dvbs_locator->put_SignalPolarisation( i_polar );
1299 if( SUCCEEDED( hr ) )
1300 hr = l.p_dvbs_locator->put_Modulation( BDA_MOD_QPSK );
1301 if( SUCCEEDED( hr ) && i_hp_fec != BDA_BCC_RATE_NOT_SET )
1302 hr = l.p_dvbs_locator->put_InnerFECRate( i_hp_fec );
1304 if( SUCCEEDED( hr ) && l_azimuth > 0 )
1305 hr = l.p_dvbs_locator->put_Azimuth( l_azimuth );
1306 if( SUCCEEDED( hr ) && l_elevation > 0 )
1307 hr = l.p_dvbs_locator->put_Elevation( l_elevation );
1308 if( SUCCEEDED( hr ) )
1309 hr = l.p_dvbs_locator->put_WestPosition( b_west );
1310 if( SUCCEEDED( hr ) )
1311 hr = l.p_dvbs_locator->put_OrbitalPosition( labs( l_longitude ) );
1315 msg_Warn( p_access, "SetDVBS: "\
1316 "Cannot set tuning parameters on Locator: hr=0x%8lx", hr );
1317 return VLC_EGENERIC;
1320 hr = l.p_dvb_tune_request->put_Locator( l.p_dvbs_locator );
1323 msg_Warn( p_access, "SetDVBS: "\
1324 "Cannot put the locator: hr=0x%8lx", hr );
1325 return VLC_EGENERIC;
1328 hr = p_scanning_tuner->Validate( l.p_dvb_tune_request );
1331 msg_Dbg( p_access, "SetDVBS: "\
1332 "Tune Request cannot be validated: hr=0x%8lx", hr );
1335 /* increments ref count for scanning tuner */
1336 hr = p_scanning_tuner->put_TuneRequest( l.p_dvb_tune_request );
1339 msg_Warn( p_access, "SetDVBS: "\
1340 "Cannot put the tune request: hr=0x%8lx", hr );
1341 return VLC_EGENERIC;
1347 /*****************************************************************************
1349 ******************************************************************************
1350 * Sets up global p_scanning_tuner and sets guid_network_type according
1351 * to the Network Type requested.
1353 * Logic: if tuner is set up and is the right network type, use it.
1354 * Otherwise, poll the tuner for the right tuning space.
1356 * Then set up a tune request and try to validate it. Finally, put
1357 * tune request and tuning space to tuner
1359 * on success, sets globals: p_scanning_tuner and guid_network_type
1361 ******************************************************************************/
1362 HRESULT BDAGraph::SetUpTuner( REFCLSID guid_this_network_type )
1368 ITuningSpaceContainer* p_tuning_space_container;
1369 IEnumTuningSpaces* p_tuning_space_enum;
1370 ITuningSpace* p_test_tuning_space;
1371 ITuneRequest* p_tune_request;
1372 IDVBTuneRequest* p_dvb_tune_request;
1374 IDigitalCableTuneRequest* p_cqam_tune_request;
1375 IATSCChannelTuneRequest* p_atsc_tune_request;
1376 ILocator* p_locator;
1377 IDVBTLocator* p_dvbt_locator;
1378 IDVBCLocator* p_dvbc_locator;
1379 IDVBSLocator* p_dvbs_locator;
1383 CLSID guid_test_network_type;
1384 char* psz_network_name;
1385 char* psz_bstr_name;
1389 p_tuning_space_container(NULL),
1390 p_tuning_space_enum(NULL),
1391 p_test_tuning_space(NULL),
1392 p_tune_request(NULL),
1393 p_dvb_tune_request(NULL),
1394 p_cqam_tune_request(NULL),
1395 p_atsc_tune_request(NULL),
1397 p_dvbt_locator(NULL),
1398 p_dvbc_locator(NULL),
1399 p_dvbs_locator(NULL),
1401 guid_test_network_type(GUID_NULL),
1402 psz_network_name(NULL),
1403 psz_bstr_name(NULL),
1408 if( p_tuning_space_enum )
1409 p_tuning_space_enum->Release();
1410 if( p_tuning_space_container )
1411 p_tuning_space_container->Release();
1412 if( p_test_tuning_space )
1413 p_test_tuning_space->Release();
1414 if( p_tune_request )
1415 p_tune_request->Release();
1416 if( p_dvb_tune_request )
1417 p_dvb_tune_request->Release();
1418 if( p_cqam_tune_request )
1419 p_cqam_tune_request->Release();
1420 if( p_atsc_tune_request )
1421 p_atsc_tune_request->Release();
1423 p_locator->Release();
1424 if( p_dvbt_locator )
1425 p_dvbt_locator->Release();
1426 if( p_dvbc_locator )
1427 p_dvbc_locator->Release();
1428 if( p_dvbs_locator )
1429 p_dvbs_locator->Release();
1430 SysFreeString( bstr_name );
1431 delete[] psz_bstr_name;
1432 free( psz_network_name );
1436 msg_Dbg( p_access, "SetUpTuner: entering" );
1439 /* We shall test for a specific Tuning space name supplied on the command
1440 * line as dvb-network-name=xxx.
1441 * For some users with multiple cards and/or multiple networks this could
1442 * be useful. This allows us to reasonably safely apply updates to the
1443 * System Tuning Space in the registry without disrupting other streams. */
1445 l.psz_network_name = var_GetNonEmptyString( p_access, "dvb-network-name" );
1447 if( l.psz_network_name )
1449 msg_Dbg( p_access, "SetUpTuner: Find Tuning Space: %s",
1450 l.psz_network_name );
1454 l.psz_network_name = new char[1];
1455 *l.psz_network_name = '\0';
1458 /* Tuner may already have been set up. If it is for the same
1459 * network type then all is well. Otherwise, reset the Tuning Space and get
1461 msg_Dbg( p_access, "SetUpTuner: Checking for tuning space" );
1462 if( !p_scanning_tuner )
1464 msg_Warn( p_access, "SetUpTuner: "\
1465 "Cannot find scanning tuner" );
1469 if( p_tuning_space )
1471 msg_Dbg( p_access, "SetUpTuner: get network type" );
1472 hr = p_tuning_space->get__NetworkType( &l.guid_test_network_type );
1475 msg_Warn( p_access, "Check: "\
1476 "Cannot get network type: hr=0x%8lx", hr );
1477 l.guid_test_network_type = GUID_NULL;
1480 msg_Dbg( p_access, "SetUpTuner: see if it's the right one" );
1481 if( l.guid_test_network_type == guid_this_network_type )
1483 msg_Dbg( p_access, "SetUpTuner: it's the right one" );
1484 SysFreeString( l.bstr_name );
1486 hr = p_tuning_space->get_UniqueName( &l.bstr_name );
1489 /* should never fail on a good tuning space */
1490 msg_Dbg( p_access, "SetUpTuner: "\
1491 "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
1495 /* Test for a specific Tuning space name supplied on the command
1496 * line as dvb-network-name=xxx */
1497 if( l.psz_bstr_name )
1498 delete[] l.psz_bstr_name;
1499 l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
1500 l.psz_bstr_name, 0, NULL, NULL );
1501 l.psz_bstr_name = new char[ l.i_name_len ];
1502 l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
1503 l.psz_bstr_name, l.i_name_len, NULL, NULL );
1505 /* if no name was requested on command line, or if the name
1506 * requested equals the name of this space, we are OK */
1507 if( *l.psz_network_name == '\0' ||
1508 strcmp( l.psz_network_name, l.psz_bstr_name ) == 0 )
1510 msg_Dbg( p_access, "SetUpTuner: Using Tuning Space: %s",
1512 /* p_tuning_space and guid_network_type are already set */
1513 /* you probably already have a tune request, also */
1514 hr = p_scanning_tuner->get_TuneRequest( &l.p_tune_request );
1515 if( SUCCEEDED( hr ) )
1519 /* CreateTuneRequest adds l.p_tune_request to p_tuning_space
1520 * l.p_tune_request->RefCount = 1 */
1521 hr = p_tuning_space->CreateTuneRequest( &l.p_tune_request );
1522 if( SUCCEEDED( hr ) )
1526 msg_Warn( p_access, "SetUpTuner: "\
1527 "Cannot Create Tune Request: hr=0x%8lx", hr );
1528 /* fall through to NoTuningSpace */
1532 /* else different guid_network_type */
1534 if( p_tuning_space )
1535 p_tuning_space->Release();
1536 p_tuning_space = NULL;
1537 /* pro forma; should have returned S_OK if we created this */
1538 if( l.p_tune_request )
1539 l.p_tune_request->Release();
1540 l.p_tune_request = NULL;
1544 /* p_tuning_space is null at this point; we have already
1545 returned S_OK if it was good. So find a tuning
1546 space on the scanning tuner. */
1548 msg_Dbg( p_access, "SetUpTuner: release TuningSpaces Enumerator" );
1549 if( l.p_tuning_space_enum )
1550 l.p_tuning_space_enum->Release();
1551 msg_Dbg( p_access, "SetUpTuner: nullify TuningSpaces Enumerator" );
1552 l.p_tuning_space_enum = NULL;
1553 msg_Dbg( p_access, "SetUpTuner: create TuningSpaces Enumerator" );
1555 hr = p_scanning_tuner->EnumTuningSpaces( &l.p_tuning_space_enum );
1558 msg_Warn( p_access, "SetUpTuner: "\
1559 "Cannot create TuningSpaces Enumerator: hr=0x%8lx", hr );
1565 msg_Dbg( p_access, "SetUpTuner: top of loop" );
1566 l.guid_test_network_type = GUID_NULL;
1567 if( l.p_test_tuning_space )
1568 l.p_test_tuning_space->Release();
1569 l.p_test_tuning_space = NULL;
1570 if( p_tuning_space )
1571 p_tuning_space->Release();
1572 p_tuning_space = NULL;
1573 SysFreeString( l.bstr_name );
1574 msg_Dbg( p_access, "SetUpTuner: need good TS enum" );
1575 if( !l.p_tuning_space_enum ) break;
1576 msg_Dbg( p_access, "SetUpTuner: next tuning space" );
1577 hr = l.p_tuning_space_enum->Next( 1, &l.p_test_tuning_space, NULL );
1578 if( hr != S_OK ) break;
1579 msg_Dbg( p_access, "SetUpTuner: get network type" );
1580 hr = l.p_test_tuning_space->get__NetworkType( &l.guid_test_network_type );
1583 msg_Warn( p_access, "Check: "\
1584 "Cannot get network type: hr=0x%8lx", hr );
1585 l.guid_test_network_type = GUID_NULL;
1587 if( l.guid_test_network_type == guid_this_network_type )
1589 msg_Dbg( p_access, "SetUpTuner: Found matching space on tuner" );
1591 SysFreeString( l.bstr_name );
1592 msg_Dbg( p_access, "SetUpTuner: get unique name" );
1594 hr = l.p_test_tuning_space->get_UniqueName( &l.bstr_name );
1597 /* should never fail on a good tuning space */
1598 msg_Dbg( p_access, "SetUpTuner: "\
1599 "Cannot get UniqueName for Tuning Space: hr=0x%8lx", hr );
1602 msg_Dbg( p_access, "SetUpTuner: convert w to multi" );
1603 if ( l.psz_bstr_name )
1604 delete[] l.psz_bstr_name;
1605 l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
1606 l.psz_bstr_name, 0, NULL, NULL );
1607 l.psz_bstr_name = new char[ l.i_name_len ];
1608 l.i_name_len = WideCharToMultiByte( CP_ACP, 0, l.bstr_name, -1,
1609 l.psz_bstr_name, l.i_name_len, NULL, NULL );
1610 msg_Dbg( p_access, "SetUpTuner: Using Tuning Space: %s",
1617 msg_Dbg( p_access, "SetUpTuner: checking what we got" );
1619 if( l.guid_test_network_type == GUID_NULL)
1621 msg_Dbg( p_access, "SetUpTuner: got null, try to clone" );
1625 msg_Dbg( p_access, "SetUpTuner: put TS" );
1626 hr = p_scanning_tuner->put_TuningSpace( l.p_test_tuning_space );
1629 msg_Dbg( p_access, "SetUpTuner: "\
1630 "cannot put tuning space: hr=0x%8lx", hr );
1634 msg_Dbg( p_access, "SetUpTuner: get default locator" );
1635 hr = l.p_test_tuning_space->get_DefaultLocator( &l.p_locator );
1638 msg_Dbg( p_access, "SetUpTuner: "\
1639 "cannot get default locator: hr=0x%8lx", hr );
1643 msg_Dbg( p_access, "SetUpTuner: create tune request" );
1644 hr = l.p_test_tuning_space->CreateTuneRequest( &l.p_tune_request );
1647 msg_Dbg( p_access, "SetUpTuner: "\
1648 "cannot create tune request: hr=0x%8lx", hr );
1652 msg_Dbg( p_access, "SetUpTuner: put locator" );
1653 hr = l.p_tune_request->put_Locator( l.p_locator );
1656 msg_Dbg( p_access, "SetUpTuner: "\
1657 "cannot put locator: hr=0x%8lx", hr );
1661 msg_Dbg( p_access, "SetUpTuner: try to validate tune request" );
1662 hr = p_scanning_tuner->Validate( l.p_tune_request );
1665 msg_Dbg( p_access, "SetUpTuner: "\
1666 "Tune Request cannot be validated: hr=0x%8lx", hr );
1669 msg_Dbg( p_access, "SetUpTuner: Attach tune request to Scanning Tuner");
1670 /* increments ref count for scanning tuner */
1671 hr = p_scanning_tuner->put_TuneRequest( l.p_tune_request );
1674 msg_Warn( p_access, "SetUpTuner: "\
1675 "Cannot submit the tune request: hr=0x%8lx", hr );
1679 msg_Dbg( p_access, "SetUpTuner: Tuning Space and Tune Request created" );
1682 /* Get the SystemTuningSpaces container
1683 * p_tuning_space_container->Refcount = 1 */
1685 msg_Warn( p_access, "SetUpTuner: won't try to clone " );
1689 /*****************************************************************************
1690 * GetNextNetworkType
1691 * helper function; this is probably best done as an Enumeration of
1693 *****************************************************************************/
1694 HRESULT BDAGraph::GetNextNetworkType( CLSID* guid_this_network_type )
1697 if( *guid_this_network_type == GUID_NULL )
1699 msg_Dbg( p_access, "GetNextNetworkType: DVB-C" );
1700 *guid_this_network_type = CLSID_DVBCNetworkProvider;
1703 if( *guid_this_network_type == CLSID_DVBCNetworkProvider )
1705 msg_Dbg( p_access, "GetNextNetworkType: DVB-T" );
1706 *guid_this_network_type = CLSID_DVBTNetworkProvider;
1709 if( *guid_this_network_type == CLSID_DVBTNetworkProvider )
1711 msg_Dbg( p_access, "GetNextNetworkType: DVB-S" );
1712 *guid_this_network_type = CLSID_DVBSNetworkProvider;
1715 if( *guid_this_network_type == CLSID_DVBSNetworkProvider )
1717 msg_Dbg( p_access, "GetNextNetworkType: ATSC" );
1718 *guid_this_network_type = CLSID_ATSCNetworkProvider;
1721 msg_Dbg( p_access, "GetNextNetworkType: failed" );
1722 *guid_this_network_type = GUID_NULL;
1728 /******************************************************************************
1730 *******************************************************************************
1731 * Check if tuner supports this network type
1733 * on success, sets globals:
1734 * systems, l_tuner_used, p_network_provider, p_scanning_tuner, p_tuner_device,
1735 * p_tuning_space, p_filter_graph
1736 ******************************************************************************/
1737 HRESULT BDAGraph::Check( REFCLSID guid_this_network_type )
1744 ITuningSpaceContainer* p_tuning_space_container;
1747 p_tuning_space_container(NULL)
1751 if( p_tuning_space_container )
1752 p_tuning_space_container->Release();
1756 msg_Dbg( p_access, "Check: entering ");
1758 /* Note that the systems global is persistent across Destroy().
1759 * So we need to see if a tuner has been physically removed from
1760 * the system since the last Check. Before we do anything,
1761 * assume that this Check will fail and remove this network type
1762 * from systems. It will be restored if the Check passes.
1765 systems &= ~( GetSystem( guid_this_network_type ) );
1768 /* If we have already have a filter graph, rebuild it*/
1769 msg_Dbg( p_access, "Check: Destroying filter graph" );
1770 if( p_filter_graph )
1772 p_filter_graph = NULL;
1773 hr = ::CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC,
1774 IID_IGraphBuilder, reinterpret_cast<void**>( &p_filter_graph ) );
1777 msg_Warn( p_access, "Check: "\
1778 "Cannot CoCreate IFilterGraph: hr=0x%8lx", hr );
1782 /* First filter in the graph is the Network Provider and
1783 * its Scanning Tuner which takes the Tune Request */
1784 if( p_network_provider )
1785 p_network_provider->Release();
1786 p_network_provider = NULL;
1787 hr = ::CoCreateInstance( guid_this_network_type, NULL, CLSCTX_INPROC_SERVER,
1788 IID_IBaseFilter, reinterpret_cast<void**>( &p_network_provider ) );
1791 msg_Warn( p_access, "Check: "\
1792 "Cannot CoCreate Network Provider: hr=0x%8lx", hr );
1796 msg_Dbg( p_access, "Check: adding Network Provider to graph");
1797 hr = p_filter_graph->AddFilter( p_network_provider, L"Network Provider" );
1800 msg_Warn( p_access, "Check: "\
1801 "Cannot load network provider: hr=0x%8lx", hr );
1805 /* Add the Network Tuner to the Network Provider. On subsequent calls,
1806 * l_tuner_used will cause a different tuner to be selected.
1808 * To select a specific device first get the parameter that nominates the
1809 * device (dvb-adapter) and use the value to initialise l_tuner_used.
1810 * Note that dvb-adapter is 1-based, while l_tuner_used is 0-based.
1811 * When FindFilter returns, check the contents of l_tuner_used.
1812 * If it is not what was selected, then the requested device was not
1813 * available, so return with an error. */
1815 long l_adapter = -1;
1816 l_adapter = var_GetInteger( p_access, "dvb-adapter" );
1817 if( l_tuner_used < 0 && l_adapter >= 0 )
1818 l_tuner_used = l_adapter - 1;
1820 /* If tuner is in cold state, we have to do a successful put_TuneRequest
1821 * before it will Connect. */
1822 msg_Dbg( p_access, "Check: Creating Scanning Tuner");
1823 if( p_scanning_tuner )
1824 p_scanning_tuner->Release();
1825 p_scanning_tuner = NULL;
1826 hr = p_network_provider->QueryInterface( IID_IScanningTuner,
1827 reinterpret_cast<void**>( &p_scanning_tuner ) );
1830 msg_Warn( p_access, "Check: "\
1831 "Cannot QI Network Provider for Scanning Tuner: hr=0x%8lx", hr );
1835 /* try to set up p_scanning_tuner */
1836 msg_Dbg( p_access, "Check: Calling SetUpTuner" );
1837 hr = SetUpTuner( guid_this_network_type );
1840 msg_Dbg( p_access, "Check: "\
1841 "Cannot set up scanner in Check mode: hr=0x%8lx", hr );
1845 msg_Dbg( p_access, "Check: "\
1846 "Calling FindFilter for KSCATEGORY_BDA_NETWORK_TUNER with "\
1847 "p_network_provider; l_tuner_used=%ld", l_tuner_used );
1848 hr = FindFilter( KSCATEGORY_BDA_NETWORK_TUNER, &l_tuner_used,
1849 p_network_provider, &p_tuner_device );
1852 msg_Warn( p_access, "Check: "\
1853 "Cannot load tuner device and connect network provider: "\
1858 if( l_adapter > 0 && l_tuner_used != l_adapter )
1860 msg_Warn( p_access, "Check: "\
1861 "Tuner device %ld is not available", l_adapter );
1865 msg_Dbg( p_access, "Check: Using adapter %ld", l_tuner_used );
1867 * already set l_tuner_used,
1870 msg_Dbg( p_access, "Check: check succeeded: hr=0x%8lx", hr );
1871 systems |= GetSystem( guid_this_network_type );
1872 msg_Dbg( p_access, "Check: returning from Check mode" );
1877 /******************************************************************************
1879 *******************************************************************************
1880 * Build the Filter Graph
1882 * connects filters and
1883 * creates the media control and registers the graph
1884 * on success, sets globals:
1885 * d_graph_register, p_media_control, p_grabber, p_sample_grabber,
1886 * p_mpeg_demux, p_transport_info
1887 ******************************************************************************/
1888 HRESULT BDAGraph::Build()
1891 long l_capture_used;
1893 AM_MEDIA_TYPE grabber_media_type;
1898 ITuningSpaceContainer* p_tuning_space_container;
1900 p_tuning_space_container(NULL)
1904 if( p_tuning_space_container )
1905 p_tuning_space_container->Release();
1909 msg_Dbg( p_access, "Build: entering");
1911 /* at this point, you've connected to a scanning tuner of the right
1914 if( !p_scanning_tuner || !p_tuner_device )
1916 msg_Warn( p_access, "Build: "\
1917 "Scanning Tuner does not exist" );
1921 hr = p_scanning_tuner->get_TuneRequest( &p_tune_request );
1924 msg_Warn( p_access, "Build: no tune request" );
1927 hr = p_scanning_tuner->get_TuningSpace( &p_tuning_space );
1930 msg_Warn( p_access, "Build: no tuning space" );
1933 hr = p_tuning_space->get__NetworkType( &guid_network_type );
1936 /* Always look for all capture devices to match the Network Tuner */
1937 l_capture_used = -1;
1938 msg_Dbg( p_access, "Build: "\
1939 "Calling FindFilter for KSCATEGORY_BDA_RECEIVER_COMPONENT with "\
1940 "p_tuner_device; l_capture_used=%ld", l_capture_used );
1941 hr = FindFilter( KSCATEGORY_BDA_RECEIVER_COMPONENT, &l_capture_used,
1942 p_tuner_device, &p_capture_device );
1945 /* Some BDA drivers do not provide a Capture Device Filter so force
1946 * the Sample Grabber to connect directly to the Tuner Device */
1947 msg_Dbg( p_access, "Build: "\
1948 "Cannot find Capture device. Connect to tuner "\
1949 "and AddRef() : hr=0x%8lx", hr );
1950 p_capture_device = p_tuner_device;
1951 p_capture_device->AddRef();
1954 if( p_sample_grabber )
1955 p_sample_grabber->Release();
1956 p_sample_grabber = NULL;
1957 /* Insert the Sample Grabber to tap into the Transport Stream. */
1958 hr = ::CoCreateInstance( CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
1959 IID_IBaseFilter, reinterpret_cast<void**>( &p_sample_grabber ) );
1962 msg_Warn( p_access, "Build: "\
1963 "Cannot load Sample Grabber Filter: hr=0x%8lx", hr );
1967 hr = p_filter_graph->AddFilter( p_sample_grabber, L"Sample Grabber" );
1970 msg_Warn( p_access, "Build: "\
1971 "Cannot add Sample Grabber Filter to graph: hr=0x%8lx", hr );
1975 /* create the sample grabber */
1977 p_grabber->Release();
1979 hr = p_sample_grabber->QueryInterface( IID_ISampleGrabber,
1980 reinterpret_cast<void**>( &p_grabber ) );
1983 msg_Warn( p_access, "Build: "\
1984 "Cannot QI Sample Grabber Filter: hr=0x%8lx", hr );
1988 /* Try the possible stream type */
1990 for( int i = 0; i < 2; i++ )
1992 ZeroMemory( &grabber_media_type, sizeof( AM_MEDIA_TYPE ) );
1993 grabber_media_type.majortype = MEDIATYPE_Stream;
1994 grabber_media_type.subtype = i == 0 ? MEDIASUBTYPE_MPEG2_TRANSPORT : KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT;
1995 msg_Dbg( p_access, "Build: "
1996 "Trying connecting with subtype %s",
1997 i == 0 ? "MEDIASUBTYPE_MPEG2_TRANSPORT" : "KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT" );
1998 hr = p_grabber->SetMediaType( &grabber_media_type );
1999 if( SUCCEEDED( hr ) )
2001 hr = Connect( p_capture_device, p_sample_grabber );
2002 if( SUCCEEDED( hr ) )
2004 msg_Dbg( p_access, "Build: "\
2005 "Connected capture device to sample grabber" );
2008 msg_Warn( p_access, "Build: "\
2009 "Cannot connect Sample Grabber to Capture device: hr=0x%8lx (try %d/2)", hr, 1+i );
2013 msg_Warn( p_access, "Build: "\
2014 "Cannot set media type on grabber filter: hr=0x%8lx (try %d/2", hr, 1+i );
2017 msg_Dbg( p_access, "Build: This is where it used to return upon success" );
2020 msg_Warn( p_access, "Build: "\
2021 "Cannot use capture device: hr=0x%8lx", hr );
2025 /* We need the MPEG2 Demultiplexer even though we are going to use the VLC
2026 * TS demuxer. The TIF filter connects to the MPEG2 demux and works with
2027 * the Network Provider filter to set up the stream */
2028 //msg_Dbg( p_access, "Build: using MPEG2 demux" );
2030 p_mpeg_demux->Release();
2031 p_mpeg_demux = NULL;
2032 hr = ::CoCreateInstance( CLSID_MPEG2Demultiplexer, NULL,
2033 CLSCTX_INPROC_SERVER, IID_IBaseFilter,
2034 reinterpret_cast<void**>( &p_mpeg_demux ) );
2037 msg_Warn( p_access, "Build: "\
2038 "Cannot CoCreateInstance MPEG2 Demultiplexer: hr=0x%8lx", hr );
2042 //msg_Dbg( p_access, "Build: adding demux" );
2043 hr = p_filter_graph->AddFilter( p_mpeg_demux, L"Demux" );
2046 msg_Warn( p_access, "Build: "\
2047 "Cannot add demux filter to graph: hr=0x%8lx", hr );
2051 hr = Connect( p_sample_grabber, p_mpeg_demux );
2054 msg_Warn( p_access, "Build: "\
2055 "Cannot connect demux to grabber: hr=0x%8lx", hr );
2059 //msg_Dbg( p_access, "Build: Connected sample grabber to demux" );
2060 /* Always look for the Transport Information Filter from the start
2061 * of the collection*/
2063 msg_Dbg( p_access, "Check: "\
2064 "Calling FindFilter for KSCATEGORY_BDA_TRANSPORT_INFORMATION with "\
2065 "p_mpeg_demux; l_tif_used=%ld", l_tif_used );
2068 hr = FindFilter( KSCATEGORY_BDA_TRANSPORT_INFORMATION, &l_tif_used,
2069 p_mpeg_demux, &p_transport_info );
2072 msg_Warn( p_access, "Build: "\
2073 "Cannot load TIF onto demux: hr=0x%8lx", hr );
2077 /* Configure the Sample Grabber to buffer the samples continuously */
2078 hr = p_grabber->SetBufferSamples( true );
2081 msg_Warn( p_access, "Build: "\
2082 "Cannot set Sample Grabber to buffering: hr=0x%8lx", hr );
2086 hr = p_grabber->SetOneShot( false );
2089 msg_Warn( p_access, "Build: "\
2090 "Cannot set Sample Grabber to multi shot: hr=0x%8lx", hr );
2094 /* Second parameter to SetCallback specifies the callback method; 0 uses
2095 * the ISampleGrabberCB::SampleCB method, which receives an IMediaSample
2097 //msg_Dbg( p_access, "Build: Adding grabber callback" );
2098 hr = p_grabber->SetCallback( this, 0 );
2101 msg_Warn( p_access, "Build: "\
2102 "Cannot set SampleGrabber Callback: hr=0x%8lx", hr );
2106 hr = Register(); /* creates d_graph_register */
2109 d_graph_register = 0;
2110 msg_Dbg( p_access, "Build: "\
2111 "Cannot register graph: hr=0x%8lx", hr );
2114 /* The Media Control is used to Run and Stop the Graph */
2115 if( p_media_control )
2116 p_media_control->Release();
2117 p_media_control = NULL;
2118 hr = p_filter_graph->QueryInterface( IID_IMediaControl,
2119 reinterpret_cast<void**>( &p_media_control ) );
2122 msg_Warn( p_access, "Build: "\
2123 "Cannot QI Media Control: hr=0x%8lx", hr );
2128 //msg_Dbg( p_access, "Build: succeeded: hr=0x%8lx", hr );
2133 HRESULT BDAGraph::ListFilters( REFCLSID this_clsid )
2140 ICreateDevEnum* p_local_system_dev_enum;
2141 IEnumMoniker* p_moniker_enum;
2142 IMoniker* p_moniker;
2143 IBaseFilter* p_filter;
2144 IBaseFilter* p_this_filter;
2145 IBindCtx* p_bind_context;
2146 IPropertyBag* p_property_bag;
2148 char* psz_downstream;
2153 p_local_system_dev_enum(NULL),
2154 p_moniker_enum(NULL),
2157 p_this_filter(NULL),
2158 p_bind_context( NULL ),
2159 p_property_bag(NULL),
2160 psz_downstream( NULL ),
2165 if( p_property_bag )
2166 p_property_bag->Release();
2167 if( p_bind_context )
2168 p_bind_context->Release();
2170 p_filter->Release();
2172 p_this_filter->Release();
2174 p_moniker->Release();
2175 if( p_moniker_enum )
2176 p_moniker_enum->Release();
2177 if( p_local_system_dev_enum )
2178 p_local_system_dev_enum->Release();
2181 if( psz_downstream )
2182 delete[] psz_downstream;
2187 // msg_Dbg( p_access, "ListFilters: Create local system_dev_enum");
2188 if( l.p_local_system_dev_enum )
2189 l.p_local_system_dev_enum->Release();
2190 l.p_local_system_dev_enum = NULL;
2191 hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
2192 IID_ICreateDevEnum, reinterpret_cast<void**>( &l.p_local_system_dev_enum ) );
2195 msg_Warn( p_access, "ListFilters: "\
2196 "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
2200 //msg_Dbg( p_access, "ListFilters: Create p_moniker_enum");
2201 if( l.p_moniker_enum )
2202 l.p_moniker_enum->Release();
2203 l.p_moniker_enum = NULL;
2204 hr = l.p_local_system_dev_enum->CreateClassEnumerator( this_clsid,
2205 &l.p_moniker_enum, 0 );
2208 msg_Warn( p_access, "ListFilters: "\
2209 "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
2213 //msg_Dbg( p_access, "ListFilters: Entering main loop" );
2216 /* We are overwriting l.p_moniker so we should Release and nullify
2217 * It is important that p_moniker and p_property_bag are fully released
2218 * l.p_filter may not be dereferenced so we could force to NULL */
2219 /* msg_Dbg( p_access, "ListFilters: top of main loop");*/
2220 //msg_Dbg( p_access, "ListFilters: releasing property bag");
2221 if( l.p_property_bag )
2222 l.p_property_bag->Release();
2223 l.p_property_bag = NULL;
2224 //msg_Dbg( p_access, "ListFilters: releasing filter");
2226 l.p_filter->Release();
2228 //msg_Dbg( p_access, "ListFilters: releasing bind context");
2229 if( l.p_bind_context )
2230 l.p_bind_context->Release();
2231 l.p_bind_context = NULL;
2232 //msg_Dbg( p_access, "ListFilters: releasing moniker");
2234 l.p_moniker->Release();
2236 //msg_Dbg( p_access, "ListFilters: trying a moniker");
2238 if( !l.p_moniker_enum ) break;
2239 hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
2240 if( hr != S_OK ) break;
2242 /* l.p_bind_context is Released at the top of the loop */
2243 hr = CreateBindCtx( 0, &l.p_bind_context );
2246 msg_Dbg( p_access, "ListFilters: "\
2247 "Cannot create bind_context, trying another: hr=0x%8lx", hr );
2251 /* l.p_filter is Released at the top of the loop */
2252 hr = l.p_moniker->BindToObject( l.p_bind_context, NULL, IID_IBaseFilter,
2253 reinterpret_cast<void**>( &l.p_filter ) );
2256 msg_Dbg( p_access, "ListFilters: "\
2257 "Cannot create p_filter, trying another: hr=0x%8lx", hr );
2261 #ifdef DEBUG_MONIKER_NAME
2262 WCHAR* pwsz_downstream = NULL;
2264 hr = l.p_moniker->GetDisplayName(l.p_bind_context, NULL,
2268 msg_Dbg( p_access, "ListFilters: "\
2269 "Cannot get display name, trying another: hr=0x%8lx", hr );
2273 if( l.psz_downstream )
2274 delete[] l.psz_downstream;
2275 l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
2276 l.psz_downstream, 0, NULL, NULL );
2277 l.psz_downstream = new char[ l.i_bstr_len ];
2278 l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
2279 l.psz_downstream, l.i_bstr_len, NULL, NULL );
2282 ::CoGetMalloc( 1, &p_alloc );
2283 p_alloc->Free( pwsz_downstream );
2285 msg_Dbg( p_access, "ListFilters: "\
2286 "Moniker name is %s", l.psz_downstream );
2288 l.psz_downstream = strdup( "Downstream" );
2290 /* l.p_property_bag is released at the top of the loop */
2291 hr = l.p_moniker->BindToStorage( NULL, NULL, IID_IPropertyBag,
2292 reinterpret_cast<void**>( &l.p_property_bag ) );
2295 msg_Dbg( p_access, "ListFilters: "\
2296 "Cannot Bind to Property Bag: hr=0x%8lx", hr );
2300 //msg_Dbg( p_access, "ListFilters: displaying another" );
2307 /******************************************************************************
2309 * Looks up all filters in a category and connects to the upstream filter until
2310 * a successful match is found. The index of the connected filter is returned.
2311 * On subsequent calls, this can be used to start from that point to find
2313 * This is used when the graph does not run because a tuner device is in use so
2314 * another one needs to be selected.
2315 ******************************************************************************/
2316 HRESULT BDAGraph::FindFilter( REFCLSID this_clsid, long* i_moniker_used,
2317 IBaseFilter* p_upstream, IBaseFilter** p_p_downstream )
2320 int i_moniker_index = -1;
2324 IEnumMoniker* p_moniker_enum;
2325 IMoniker* p_moniker;
2326 IBindCtx* p_bind_context;
2327 IPropertyBag* p_property_bag;
2331 char* psz_downstream;
2335 p_moniker_enum(NULL),
2337 p_bind_context( NULL ),
2338 p_property_bag(NULL),
2339 psz_upstream( NULL ),
2340 psz_downstream( NULL )
2342 ::VariantInit(&var_bstr);
2346 if( p_moniker_enum )
2347 p_moniker_enum->Release();
2349 p_moniker->Release();
2350 if( p_bind_context )
2351 p_bind_context->Release();
2352 if( p_property_bag )
2353 p_property_bag->Release();
2355 delete[] psz_upstream;
2356 if( psz_downstream )
2357 delete[] psz_downstream;
2359 ::VariantClear(&var_bstr);
2363 /* create system_dev_enum the first time through, or preserve the
2364 * existing one to loop through classes */
2365 if( !p_system_dev_enum )
2367 msg_Dbg( p_access, "FindFilter: Create p_system_dev_enum");
2368 hr = ::CoCreateInstance( CLSID_SystemDeviceEnum, 0, CLSCTX_INPROC,
2369 IID_ICreateDevEnum, reinterpret_cast<void**>( &p_system_dev_enum ) );
2372 msg_Warn( p_access, "FindFilter: "\
2373 "Cannot CoCreate SystemDeviceEnum: hr=0x%8lx", hr );
2378 msg_Dbg( p_access, "FindFilter: Create p_moniker_enum");
2379 hr = p_system_dev_enum->CreateClassEnumerator( this_clsid,
2380 &l.p_moniker_enum, 0 );
2383 msg_Warn( p_access, "FindFilter: "\
2384 "Cannot CreateClassEnumerator: hr=0x%8lx", hr );
2388 msg_Dbg( p_access, "FindFilter: get filter name");
2389 hr = GetFilterName( p_upstream, &l.psz_upstream );
2392 msg_Warn( p_access, "FindFilter: "\
2393 "Cannot GetFilterName: hr=0x%8lx", hr );
2397 msg_Dbg( p_access, "FindFilter: "\
2398 "called with i_moniker_used=%ld, " \
2399 "p_upstream = %s", *i_moniker_used, l.psz_upstream );
2403 /* We are overwriting l.p_moniker so we should Release and nullify
2404 * It is important that p_moniker and p_property_bag are fully released */
2405 msg_Dbg( p_access, "FindFilter: top of main loop");
2406 if( l.p_property_bag )
2407 l.p_property_bag->Release();
2408 l.p_property_bag = NULL;
2409 msg_Dbg( p_access, "FindFilter: releasing bind context");
2410 if( l.p_bind_context )
2411 l.p_bind_context->Release();
2412 l.p_bind_context = NULL;
2413 msg_Dbg( p_access, "FindFilter: releasing moniker");
2415 l.p_moniker->Release();
2416 msg_Dbg( p_access, "FindFilter: null moniker");
2419 msg_Dbg( p_access, "FindFilter: quit if no enum");
2420 if( !l.p_moniker_enum ) break;
2421 msg_Dbg( p_access, "FindFilter: trying a moniker");
2422 hr = l.p_moniker_enum->Next( 1, &l.p_moniker, 0 );
2423 if( hr != S_OK ) break;
2427 /* Skip over devices already found on previous calls */
2428 msg_Dbg( p_access, "FindFilter: skip previously found devices");
2430 if( i_moniker_index <= *i_moniker_used ) continue;
2431 *i_moniker_used = i_moniker_index;
2433 /* l.p_bind_context is Released at the top of the loop */
2434 msg_Dbg( p_access, "FindFilter: create bind context");
2435 hr = CreateBindCtx( 0, &l.p_bind_context );
2438 msg_Dbg( p_access, "FindFilter: "\
2439 "Cannot create bind_context, trying another: hr=0x%8lx", hr );
2443 msg_Dbg( p_access, "FindFilter: try to create downstream filter");
2444 *p_p_downstream = NULL;
2445 hr = l.p_moniker->BindToObject( l.p_bind_context, NULL, IID_IBaseFilter,
2446 reinterpret_cast<void**>( p_p_downstream ) );
2449 msg_Dbg( p_access, "FindFilter: "\
2450 "Cannot bind to downstream, trying another: hr=0x%8lx", hr );
2454 #ifdef DEBUG_MONIKER_NAME
2455 msg_Dbg( p_access, "FindFilter: get downstream filter name");
2457 WCHAR* pwsz_downstream = NULL;
2459 hr = l.p_moniker->GetDisplayName(l.p_bind_context, NULL,
2463 msg_Dbg( p_access, "FindFilter: "\
2464 "Cannot get display name, trying another: hr=0x%8lx", hr );
2468 if( l.psz_downstream )
2469 delete[] l.psz_downstream;
2470 l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
2471 l.psz_downstream, 0, NULL, NULL );
2472 l.psz_downstream = new char[ l.i_bstr_len ];
2473 l.i_bstr_len = WideCharToMultiByte( CP_ACP, 0, pwsz_downstream, -1,
2474 l.psz_downstream, l.i_bstr_len, NULL, NULL );
2477 ::CoGetMalloc( 1, &p_alloc );
2478 p_alloc->Free( pwsz_downstream );
2481 l.psz_downstream = strdup( "Downstream" );
2484 /* l.p_property_bag is released at the top of the loop */
2485 msg_Dbg( p_access, "FindFilter: "\
2486 "Moniker name is %s, binding to storage", l.psz_downstream );
2487 hr = l.p_moniker->BindToStorage( l.p_bind_context, NULL,
2488 IID_IPropertyBag, reinterpret_cast<void**>( &l.p_property_bag ) );
2491 msg_Dbg( p_access, "FindFilter: "\
2492 "Cannot Bind to Property Bag: hr=0x%8lx", hr );
2496 msg_Dbg( p_access, "FindFilter: read friendly name");
2497 hr = l.p_property_bag->Read( L"FriendlyName", &l.var_bstr, NULL );
2500 msg_Dbg( p_access, "FindFilter: "\
2501 "Cannot read friendly name, next?: hr=0x%8lx", hr );
2505 msg_Dbg( p_access, "FindFilter: add filter to graph" );
2506 hr = p_filter_graph->AddFilter( *p_p_downstream, l.var_bstr.bstrVal );
2509 msg_Dbg( p_access, "FindFilter: "\
2510 "Cannot add filter, trying another: hr=0x%8lx", hr );
2514 msg_Dbg( p_access, "FindFilter: "\
2515 "Trying to Connect %s to %s", l.psz_upstream, l.psz_downstream );
2516 hr = Connect( p_upstream, *p_p_downstream );
2517 if( SUCCEEDED( hr ) )
2519 msg_Dbg( p_access, "FindFilter: Connected %s", l.psz_downstream );
2523 /* Not the filter we want so unload and try the next one */
2524 /* Warning: RemoveFilter does an undocumented Release()
2525 * on pointer but does not set it to NULL */
2526 msg_Dbg( p_access, "FindFilter: Removing filter" );
2527 hr = p_filter_graph->RemoveFilter( *p_p_downstream );
2530 msg_Warn( p_access, "FindFilter: "\
2531 "Failed unloading Filter: hr=0x%8lx", hr );
2534 msg_Dbg( p_access, "FindFilter: trying another" );
2539 msg_Warn( p_access, "FindFilter: No filter connected" );
2544 /*****************************************************************************
2545 * Connect is called from Build to enumerate and connect pins
2546 *****************************************************************************/
2547 HRESULT BDAGraph::Connect( IBaseFilter* p_upstream, IBaseFilter* p_downstream )
2549 HRESULT hr = E_FAIL;
2553 IPin* p_pin_upstream;
2554 IPin* p_pin_downstream;
2555 IEnumPins* p_pin_upstream_enum;
2556 IEnumPins* p_pin_downstream_enum;
2559 char* psz_downstream;
2562 p_pin_upstream(NULL), p_pin_downstream(NULL),
2563 p_pin_upstream_enum(NULL), p_pin_downstream_enum(NULL),
2565 psz_upstream( NULL ),
2566 psz_downstream( NULL )
2571 p_pin_temp->Release();
2572 if( p_pin_downstream )
2573 p_pin_downstream->Release();
2574 if( p_pin_upstream )
2575 p_pin_upstream->Release();
2576 if( p_pin_downstream_enum )
2577 p_pin_downstream_enum->Release();
2578 if( p_pin_upstream_enum )
2579 p_pin_upstream_enum->Release();
2581 delete[] psz_upstream;
2582 if( psz_downstream )
2583 delete[] psz_downstream;
2587 PIN_DIRECTION pin_dir;
2589 //msg_Dbg( p_access, "Connect: entering" );
2590 hr = p_upstream->EnumPins( &l.p_pin_upstream_enum );
2593 msg_Warn( p_access, "Connect: "\
2594 "Cannot get upstream filter enumerator: hr=0x%8lx", hr );
2600 /* Release l.p_pin_upstream before next iteration */
2601 if( l.p_pin_upstream )
2602 l.p_pin_upstream ->Release();
2603 l.p_pin_upstream = NULL;
2604 if( !l.p_pin_upstream_enum ) break;
2605 hr = l.p_pin_upstream_enum->Next( 1, &l.p_pin_upstream, 0 );
2606 if( hr != S_OK ) break;
2608 //msg_Dbg( p_access, "Connect: get pin name");
2609 hr = GetPinName( l.p_pin_upstream, &l.psz_upstream );
2612 msg_Warn( p_access, "Connect: "\
2613 "Cannot GetPinName: hr=0x%8lx", hr );
2616 //msg_Dbg( p_access, "Connect: p_pin_upstream = %s", l.psz_upstream );
2618 hr = l.p_pin_upstream->QueryDirection( &pin_dir );
2621 msg_Warn( p_access, "Connect: "\
2622 "Cannot get upstream filter pin direction: hr=0x%8lx", hr );
2626 hr = l.p_pin_upstream->ConnectedTo( &l.p_pin_downstream );
2627 if( SUCCEEDED( hr ) )
2629 l.p_pin_downstream->Release();
2630 l.p_pin_downstream = NULL;
2633 if( FAILED( hr ) && hr != VFW_E_NOT_CONNECTED )
2635 msg_Warn( p_access, "Connect: "\
2636 "Cannot check upstream filter connection: hr=0x%8lx", hr );
2640 if( ( pin_dir == PINDIR_OUTPUT ) && ( hr == VFW_E_NOT_CONNECTED ) )
2642 /* The upstream pin is not yet connected so check each pin on the
2643 * downstream filter */
2644 //msg_Dbg( p_access, "Connect: enumerating downstream pins" );
2645 hr = p_downstream->EnumPins( &l.p_pin_downstream_enum );
2648 msg_Warn( p_access, "Connect: Cannot get "\
2649 "downstream filter enumerator: hr=0x%8lx", hr );
2655 /* Release l.p_pin_downstream before next iteration */
2656 if( l.p_pin_downstream )
2657 l.p_pin_downstream ->Release();
2658 l.p_pin_downstream = NULL;
2659 if( !l.p_pin_downstream_enum ) break;
2660 hr = l.p_pin_downstream_enum->Next( 1, &l.p_pin_downstream, 0 );
2661 if( hr != S_OK ) break;
2663 //msg_Dbg( p_access, "Connect: get pin name");
2664 hr = GetPinName( l.p_pin_downstream, &l.psz_downstream );
2667 msg_Warn( p_access, "Connect: "\
2668 "Cannot GetPinName: hr=0x%8lx", hr );
2672 msg_Dbg( p_access, "Connect: Trying p_downstream = %s",
2676 hr = l.p_pin_downstream->QueryDirection( &pin_dir );
2679 msg_Warn( p_access, "Connect: Cannot get "\
2680 "downstream filter pin direction: hr=0x%8lx", hr );
2684 /* Looking for a free Pin to connect to
2685 * A connected Pin may have an reference count > 1
2686 * so Release and nullify the pointer */
2687 hr = l.p_pin_downstream->ConnectedTo( &l.p_pin_temp );
2688 if( SUCCEEDED( hr ) )
2690 l.p_pin_temp->Release();
2691 l.p_pin_temp = NULL;
2694 if( hr != VFW_E_NOT_CONNECTED )
2698 msg_Warn( p_access, "Connect: Cannot check "\
2699 "downstream filter connection: hr=0x%8lx", hr );
2704 if( ( pin_dir == PINDIR_INPUT ) &&
2705 ( hr == VFW_E_NOT_CONNECTED ) )
2707 //msg_Dbg( p_access, "Connect: trying to connect pins" );
2709 hr = p_filter_graph->ConnectDirect( l.p_pin_upstream,
2710 l.p_pin_downstream, NULL );
2711 if( SUCCEEDED( hr ) )
2713 /* If we arrive here then we have a matching pair of
2718 /* If we arrive here it means this downstream pin is not
2719 * suitable so try the next downstream pin.
2720 * l.p_pin_downstream is released at the top of the loop */
2723 /* If we arrive here then we ran out of pins before we found a
2724 * suitable one. Release outstanding refcounts */
2725 if( l.p_pin_downstream_enum )
2726 l.p_pin_downstream_enum->Release();
2727 l.p_pin_downstream_enum = NULL;
2728 if( l.p_pin_downstream )
2729 l.p_pin_downstream->Release();
2730 l.p_pin_downstream = NULL;
2732 /* If we arrive here it means this upstream pin is not suitable
2733 * so try the next upstream pin
2734 * l.p_pin_upstream is released at the top of the loop */
2737 /* If we arrive here it means we did not find any pair of suitable pins
2738 * Outstanding refcounts are released in the destructor */
2739 //msg_Dbg( p_access, "Connect: No pins connected" );
2743 /*****************************************************************************
2744 * Start uses MediaControl to start the graph
2745 *****************************************************************************/
2746 HRESULT BDAGraph::Start()
2749 OAFilterState i_state; /* State_Stopped, State_Paused, State_Running */
2751 msg_Dbg( p_access, "Start: entering" );
2753 if( !p_media_control )
2755 msg_Warn( p_access, "Start: Media Control has not been created" );
2759 msg_Dbg( p_access, "Start: Run()" );
2760 hr = p_media_control->Run();
2761 if( SUCCEEDED( hr ) )
2763 msg_Dbg( p_access, "Start: Graph started, hr=0x%lx", hr );
2767 msg_Dbg( p_access, "Start: would not start, will retry" );
2768 /* Query the state of the graph - timeout after 100 milliseconds */
2769 while( (hr = p_media_control->GetState( 100, &i_state) ) != S_OK )
2774 "Start: Cannot get Graph state: hr=0x%8lx", hr );
2779 msg_Dbg( p_access, "Start: got state" );
2780 if( i_state == State_Running )
2782 msg_Dbg( p_access, "Graph started after a delay, hr=0x%lx", hr );
2786 /* The Graph is not running so stop it and return an error */
2787 msg_Warn( p_access, "Start: Graph not started: %d", (int)i_state );
2788 hr = p_media_control->StopWhenReady(); /* Instead of Stop() */
2792 "Start: Cannot stop Graph after Run failed: hr=0x%8lx", hr );
2799 /*****************************************************************************
2800 * Pop the stream of data
2801 *****************************************************************************/
2802 ssize_t BDAGraph::Pop(void *buf, size_t len)
2804 return output.Pop(buf, len);
2807 /******************************************************************************
2808 * SampleCB - Callback when the Sample Grabber has a sample
2809 ******************************************************************************/
2810 STDMETHODIMP BDAGraph::SampleCB( double /*date*/, IMediaSample *p_sample )
2812 if( p_sample->IsDiscontinuity() == S_OK )
2813 msg_Warn( p_access, "BDA SampleCB: Sample Discontinuity.");
2815 const size_t i_sample_size = p_sample->GetActualDataLength();
2817 /* The buffer memory is owned by the media sample object, and is automatically
2818 * released when the media sample is destroyed. The caller should not free or
2819 * reallocate the buffer. */
2820 BYTE *p_sample_data;
2821 p_sample->GetPointer( &p_sample_data );
2823 if( i_sample_size > 0 && p_sample_data )
2825 block_t *p_block = block_Alloc( i_sample_size );
2829 memcpy( p_block->p_buffer, p_sample_data, i_sample_size );
2830 output.Push( p_block );
2836 STDMETHODIMP BDAGraph::BufferCB( double /*date*/, BYTE* /*buffer*/,
2837 long /*buffer_len*/ )
2842 /******************************************************************************
2843 * removes each filter from the graph
2844 ******************************************************************************/
2845 HRESULT BDAGraph::Destroy()
2849 // msg_Dbg( p_access, "Destroy: media control 1" );
2850 if( p_media_control )
2851 p_media_control->StopWhenReady(); /* Instead of Stop() */
2853 // msg_Dbg( p_access, "Destroy: deregistering graph" );
2854 if( d_graph_register )
2857 // msg_Dbg( p_access, "Destroy: calling Empty" );
2860 // msg_Dbg( p_access, "Destroy: TIF" );
2861 if( p_transport_info )
2863 /* Warning: RemoveFilter does an undocumented Release()
2864 * on pointer but does not set it to NULL */
2865 hr = p_filter_graph->RemoveFilter( p_transport_info );
2868 msg_Dbg( p_access, "Destroy: "\
2869 "Failed unloading TIF: hr=0x%8lx", hr );
2871 p_transport_info = NULL;
2874 // msg_Dbg( p_access, "Destroy: demux" );
2877 p_filter_graph->RemoveFilter( p_mpeg_demux );
2880 msg_Dbg( p_access, "Destroy: "\
2881 "Failed unloading demux: hr=0x%8lx", hr );
2883 p_mpeg_demux = NULL;
2886 // msg_Dbg( p_access, "Destroy: sample grabber" );
2889 mem_ref = p_grabber->Release();
2892 msg_Dbg( p_access, "Destroy: "\
2893 "Sample grabber mem_ref (varies): mem_ref=%ld", mem_ref );
2898 // msg_Dbg( p_access, "Destroy: sample grabber filter" );
2899 if( p_sample_grabber )
2901 hr = p_filter_graph->RemoveFilter( p_sample_grabber );
2902 p_sample_grabber = NULL;
2905 msg_Dbg( p_access, "Destroy: "\
2906 "Failed unloading sampler: hr=0x%8lx", hr );
2910 // msg_Dbg( p_access, "Destroy: capture device" );
2911 if( p_capture_device )
2913 p_filter_graph->RemoveFilter( p_capture_device );
2916 msg_Dbg( p_access, "Destroy: "\
2917 "Failed unloading capture device: hr=0x%8lx", hr );
2919 p_capture_device = NULL;
2922 // msg_Dbg( p_access, "Destroy: tuner device" );
2923 if( p_tuner_device )
2925 //msg_Dbg( p_access, "Destroy: remove filter on tuner device" );
2926 hr = p_filter_graph->RemoveFilter( p_tuner_device );
2927 //msg_Dbg( p_access, "Destroy: force tuner device to NULL" );
2928 p_tuner_device = NULL;
2931 msg_Dbg( p_access, "Destroy: "\
2932 "Failed unloading tuner device: hr=0x%8lx", hr );
2936 // msg_Dbg( p_access, "Destroy: scanning tuner" );
2937 if( p_scanning_tuner )
2939 mem_ref = p_scanning_tuner->Release();
2942 msg_Dbg( p_access, "Destroy: "\
2943 "Scanning tuner mem_ref (normally 2 if warm, "\
2944 "3 if active): mem_ref=%ld", mem_ref );
2946 p_scanning_tuner = NULL;
2949 // msg_Dbg( p_access, "Destroy: net provider" );
2950 if( p_network_provider )
2952 hr = p_filter_graph->RemoveFilter( p_network_provider );
2953 p_network_provider = NULL;
2956 msg_Dbg( p_access, "Destroy: "\
2957 "Failed unloading net provider: hr=0x%8lx", hr );
2961 // msg_Dbg( p_access, "Destroy: filter graph" );
2962 if( p_filter_graph )
2964 mem_ref = p_filter_graph->Release();
2967 msg_Dbg( p_access, "Destroy: "\
2968 "Filter graph mem_ref (normally 1 if active): mem_ref=%ld",
2971 p_filter_graph = NULL;
2974 /* first call to FindFilter creates p_system_dev_enum */
2976 // msg_Dbg( p_access, "Destroy: system dev enum" );
2977 if( p_system_dev_enum )
2979 mem_ref = p_system_dev_enum->Release();
2982 msg_Dbg( p_access, "Destroy: "\
2983 "System_dev_enum mem_ref: mem_ref=%ld", mem_ref );
2985 p_system_dev_enum = NULL;
2988 // msg_Dbg( p_access, "Destroy: media control 2" );
2989 if( p_media_control )
2991 msg_Dbg( p_access, "Destroy: release media control" );
2992 mem_ref = p_media_control->Release();
2995 msg_Dbg( p_access, "Destroy: "\
2996 "Media control mem_ref: mem_ref=%ld", mem_ref );
2998 msg_Dbg( p_access, "Destroy: force media control to NULL" );
2999 p_media_control = NULL;
3002 d_graph_register = 0;
3004 guid_network_type = GUID_NULL;
3006 // msg_Dbg( p_access, "Destroy: returning" );
3010 /*****************************************************************************
3011 * Add/Remove a DirectShow filter graph to/from the Running Object Table.
3012 * Allows GraphEdit to "spy" on a remote filter graph.
3013 ******************************************************************************/
3014 HRESULT BDAGraph::Register()
3019 IMoniker* p_moniker;
3020 IRunningObjectTable* p_ro_table;
3028 p_moniker->Release();
3030 p_ro_table->Release();
3033 WCHAR pwsz_graph_name[128];
3036 hr = ::GetRunningObjectTable( 0, &l.p_ro_table );
3039 msg_Warn( p_access, "Register: Cannot get ROT: hr=0x%8lx", hr );
3043 size_t len = sizeof(pwsz_graph_name) / sizeof(pwsz_graph_name[0]);
3044 _snwprintf( pwsz_graph_name, len - 1, L"VLC BDA Graph %08x Pid %08x",
3045 (DWORD_PTR) p_filter_graph, ::GetCurrentProcessId() );
3046 pwsz_graph_name[len-1] = 0;
3047 hr = CreateItemMoniker( L"!", pwsz_graph_name, &l.p_moniker );
3050 msg_Warn( p_access, "Register: Cannot Create Moniker: hr=0x%8lx", hr );
3053 hr = l.p_ro_table->Register( ROTFLAGS_REGISTRATIONKEEPSALIVE,
3054 p_filter_graph, l.p_moniker, &d_graph_register );
3057 msg_Warn( p_access, "Register: Cannot Register Graph: hr=0x%8lx", hr );
3061 msg_Dbg( p_access, "Register: registered Graph: %S", pwsz_graph_name );
3065 void BDAGraph::Deregister()
3068 IRunningObjectTable* p_ro_table;
3069 hr = ::GetRunningObjectTable( 0, &p_ro_table );
3070 /* docs say this does a Release() on d_graph_register stuff */
3071 if( SUCCEEDED( hr ) )
3072 p_ro_table->Revoke( d_graph_register );
3073 d_graph_register = 0;
3074 p_ro_table->Release();
3077 HRESULT BDAGraph::GetFilterName( IBaseFilter* p_filter, char** psz_bstr_name )
3079 FILTER_INFO filter_info;
3082 hr = p_filter->QueryFilterInfo(&filter_info);
3085 int i_name_len = WideCharToMultiByte( CP_ACP, 0, filter_info.achName,
3086 -1, *psz_bstr_name, 0, NULL, NULL );
3087 *psz_bstr_name = new char[ i_name_len ];
3088 i_name_len = WideCharToMultiByte( CP_ACP, 0, filter_info.achName,
3089 -1, *psz_bstr_name, i_name_len, NULL, NULL );
3091 // The FILTER_INFO structure holds a pointer to the Filter Graph
3092 // Manager, with a reference count that must be released.
3093 if( filter_info.pGraph )
3094 filter_info.pGraph->Release();
3098 HRESULT BDAGraph::GetPinName( IPin* p_pin, char** psz_bstr_name )
3103 hr = p_pin->QueryPinInfo(&pin_info);
3106 int i_name_len = WideCharToMultiByte( CP_ACP, 0, pin_info.achName,
3107 -1, *psz_bstr_name, 0, NULL, NULL );
3108 *psz_bstr_name = new char[ i_name_len ];
3109 i_name_len = WideCharToMultiByte( CP_ACP, 0, pin_info.achName,
3110 -1, *psz_bstr_name, i_name_len, NULL, NULL );
3112 // The PIN_INFO structure holds a pointer to the Filter,
3113 // with a referenppce count that must be released.
3114 if( pin_info.pFilter )
3115 pin_info.pFilter->Release();