public static void ConnectFilters(IGraphBuilder graphBuilder, IPin sourcePin, IPin destPin, bool useIntelligentConnect)
        {
            int hr = 0;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            if (sourcePin.IsNull())
            {
                throw new ArgumentNullException("sourcePin");
            }

            if (destPin.IsNull())
            {
                throw new ArgumentNullException("destPin");
            }

            if (useIntelligentConnect)
            {
                hr = graphBuilder.Connect(sourcePin, destPin);
                DsError.ThrowExceptionForHR(hr);
            }
            else
            {
                hr = graphBuilder.ConnectDirect(sourcePin, destPin, null);
                DsError.ThrowExceptionForHR(hr);
            }
        }
		public static IBaseFilter AddFilterFromClsid(IGraphBuilder graphBuilder, Guid clsid, string name)
		{
			int hr = 0;
			IBaseFilter filter = null;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			try
			{
				Type type = Type.GetTypeFromCLSID(clsid);
				filter = (IBaseFilter)Activator.CreateInstance(type);

				hr = graphBuilder.AddFilter(filter, name);
				DsError.ThrowExceptionForHR(hr);
			}
			catch
			{
				if (filter.NotNull())
				{
					Marshal.ReleaseComObject(filter);
					filter = null;
				}
			}

			return filter;
		}
        public static IBaseFilter AddFilterFromClsid(IGraphBuilder graphBuilder, Guid clsid, string name)
        {
            int         hr     = 0;
            IBaseFilter filter = null;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            try
            {
                Type type = Type.GetTypeFromCLSID(clsid);
                filter = (IBaseFilter)Activator.CreateInstance(type);

                hr = graphBuilder.AddFilter(filter, name);
                DsError.ThrowExceptionForHR(hr);
            }
            catch
            {
                if (filter.NotNull())
                {
                    Marshal.ReleaseComObject(filter);
                    filter = null;
                }
            }

            return(filter);
        }
        public static void RemoveAllFilters(IGraphBuilder graphBuilder)
        {
            int          hr = 0;
            IEnumFilters enumFilters;
            ArrayList    filtersArray = new ArrayList();

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            hr = graphBuilder.EnumFilters(out enumFilters);
            DsError.ThrowExceptionForHR(hr);

            try
            {
                IBaseFilter[] filters = new IBaseFilter[1];

                while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
                {
                    filtersArray.Add(filters[0]);
                }
            }
            finally
            {
                Marshal.ReleaseComObject(enumFilters);
            }

            foreach (IBaseFilter filter in filtersArray)
            {
                hr = graphBuilder.RemoveFilter(filter);
                Marshal.ReleaseComObject(filter);
            }
        }
        public static void DisconnectAllPins(IGraphBuilder graphBuilder)
        {
            int          hr = 0;
            IEnumFilters enumFilters;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            hr = graphBuilder.EnumFilters(out enumFilters);
            DsError.ThrowExceptionForHR(hr);

            try
            {
                IBaseFilter[] filters = new IBaseFilter[1];

                while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
                {
                    try
                    {
                        DisconnectPins(filters[0]);
                    }
                    catch { }
                    Marshal.ReleaseComObject(filters[0]);
                }
            }
            finally
            {
                Marshal.ReleaseComObject(enumFilters);
            }
        }
        public static bool RenderPin(IGraphBuilder graphBuilder, IBaseFilter source, string pinName)
        {
            int hr = 0;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            if (source.IsNull())
            {
                throw new ArgumentNullException("source");
            }

            IPin pin = DsFindPin.ByName(source, pinName);

            if (pin.NotNull())
            {
                hr = graphBuilder.Render(pin);
                Marshal.ReleaseComObject(pin);

                return(hr >= 0);
            }

            return(false);
        }
        public static IBaseFilter FindFilterByClsid(IGraphBuilder graphBuilder, Guid filterClsid)
        {
            int          hr          = 0;
            IBaseFilter  filter      = null;
            IEnumFilters enumFilters = null;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            hr = graphBuilder.EnumFilters(out enumFilters);
            if (hr == 0)
            {
                IBaseFilter[] filters = new IBaseFilter[1];

                while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
                {
                    Guid clsid;

                    hr = filters[0].GetClassID(out clsid);

                    if ((hr == 0) && (clsid == filterClsid))
                    {
                        filter = filters[0];
                        break;
                    }

                    Marshal.ReleaseComObject(filters[0]);
                }
                Marshal.ReleaseComObject(enumFilters);
            }

            return(filter);
        }
        /// <summary>
        /// Add a filter to a DirectShow Graph using its name
        /// </summary>
        /// <param name="graphBuilder">the IGraphBuilder interface of the graph</param>
        /// <param name="deviceCategory">the filter category (see DirectShowLib.FilterCategory)</param>
        /// <param name="friendlyName">the filter name (case-sensitive)</param>
        /// <returns>an instance of the filter if the method successfully created it, null if not</returns>
        /// <example>This sample shows how to programmatically add a NVIDIA Video decoder filter to a graph
        /// <code>
        /// filter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "NVIDIA Video Decoder");
        /// </code>
        /// </example>
        /// <exception cref="System.ArgumentNullException">Thrown if graphBuilder is null</exception>
        /// <exception cref="System.Runtime.InteropServices.COMException">Thrown if errors occur when the filter is add to the graph</exception>

        public static IBaseFilter AddFilterByName(IGraphBuilder graphBuilder, Guid deviceCategory, string friendlyName)
        {
            int         hr     = 0;
            IBaseFilter filter = null;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            DsDevice[] devices = DsDevice.GetDevicesOfCat(deviceCategory);

            for (int i = 0; i < devices.Length; i++)
            {
                if (!devices[i].Name.Equals(friendlyName))
                {
                    continue;
                }

                hr = (graphBuilder as IFilterGraph2).AddSourceFilterForMoniker(devices[i].Mon, null, friendlyName, out filter);
                DsError.ThrowExceptionForHR(hr);

                break;
            }

            return(filter);
        }
        public static void LoadGraphFile(IGraphBuilder graphBuilder, string fileName)
        {
            int      hr      = 0;
            IStorage storage = null;

#if USING_NET11
            UCOMIStream stream = null;
#else
            IStream stream = null;
#endif

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            try
            {
                if (NativeMethods.StgIsStorageFile(fileName) != 0)
                {
                    throw new ArgumentException();
                }

                hr = NativeMethods.StgOpenStorage(
                    fileName,
                    null,
                    STGM.Transacted | STGM.Read | STGM.ShareDenyWrite,
                    IntPtr.Zero,
                    0,
                    out storage
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = storage.OpenStream(
                    @"ActiveMovieGraph",
                    IntPtr.Zero,
                    STGM.Read | STGM.ShareExclusive,
                    0,
                    out stream
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = (graphBuilder as IPersistStream).Load(stream);
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (stream.NotNull())
                {
                    Marshal.ReleaseComObject(stream);
                }
                if (storage.NotNull())
                {
                    Marshal.ReleaseComObject(storage);
                }
            }
        }
        public static void SaveGraphFile(IGraphBuilder graphBuilder, string fileName)
        {
            int      hr      = 0;
            IStorage storage = null;

#if USING_NET11
            UCOMIStream stream = null;
#else
            IStream stream = null;
#endif

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            try
            {
                hr = NativeMethods.StgCreateDocfile(
                    fileName,
                    STGM.Create | STGM.Transacted | STGM.ReadWrite | STGM.ShareExclusive,
                    0,
                    out storage
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = storage.CreateStream(
                    @"ActiveMovieGraph",
                    STGM.Write | STGM.Create | STGM.ShareExclusive,
                    0,
                    0,
                    out stream
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = (graphBuilder as IPersistStream).Save(stream, true);
                Marshal.ThrowExceptionForHR(hr);

                hr = storage.Commit(STGC.Default);
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (stream.NotNull())
                {
                    Marshal.ReleaseComObject(stream);
                }
                if (storage.NotNull())
                {
                    Marshal.ReleaseComObject(storage);
                }
            }
        }
        public static IBaseFilter AddFilterByDevicePath(IGraphBuilder graphBuilder, string devicePath, string name)
        {
            int         hr     = 0;
            IBaseFilter filter = null;

#if USING_NET11
            UCOMIBindCtx bindCtx = null;
            UCOMIMoniker moniker = null;
#else
            IBindCtx bindCtx = null;
            IMoniker moniker = null;
#endif
            int eaten;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            try
            {
                hr = NativeMethods.CreateBindCtx(0, out bindCtx);
                Marshal.ThrowExceptionForHR(hr);

                hr = NativeMethods.MkParseDisplayName(bindCtx, devicePath, out eaten, out moniker);
                Marshal.ThrowExceptionForHR(hr);

                hr = (graphBuilder as IFilterGraph2).AddSourceFilterForMoniker(moniker, bindCtx, name, out filter);
                DsError.ThrowExceptionForHR(hr);
            }
            catch
            {
                // An error occur. Just returning null...
            }
            finally
            {
                if (bindCtx.NotNull())
                {
                    Marshal.ReleaseComObject(bindCtx);
                }
                if (moniker.NotNull())
                {
                    Marshal.ReleaseComObject(moniker);
                }
            }

            return(filter);
        }
        public static IBaseFilter FindFilterByName(IGraphBuilder graphBuilder, string filterName)
        {
            int          hr          = 0;
            IBaseFilter  filter      = null;
            IEnumFilters enumFilters = null;

            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            hr = graphBuilder.EnumFilters(out enumFilters);
            if (hr == 0)
            {
                IBaseFilter[] filters = new IBaseFilter[1];

                while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
                {
                    FilterInfo filterInfo;

                    hr = filters[0].QueryFilterInfo(out filterInfo);
                    if (hr == 0)
                    {
                        if (filterInfo.pGraph.NotNull())
                        {
                            Marshal.ReleaseComObject(filterInfo.pGraph);
                        }

                        if (filterInfo.achName.Equals(filterName))
                        {
                            filter = filters[0];
                            break;
                        }
                    }

                    Marshal.ReleaseComObject(filters[0]);
                }
                Marshal.ReleaseComObject(enumFilters);
            }

            return(filter);
        }
        /// <summary>
        /// Connect pins from two filters
        /// </summary>
        /// <param name="graphBuilder">the IGraphBuilder interface of the graph</param>
        /// <param name="upFilter">the upstream filter</param>
        /// <param name="sourcePinName">the upstream filter pin name</param>
        /// <param name="downFilter">the downstream filter</param>
        /// <param name="destPinName">the downstream filter pin name</param>
        /// <param name="useIntelligentConnect">indicate if the method should use DirectShow's Intelligent Connect</param>
        /// <exception cref="System.ArgumentNullException">Thrown if graphBuilder, upFilter or downFilter are null</exception>
        /// <exception cref="System.ArgumentException">Thrown if pin names are not found in filters</exception>
        /// <exception cref="System.Runtime.InteropServices.COMException">Thrown if pins can't connect</exception>
        /// <remarks>
        /// If useIntelligentConnect is true, this method can add missing filters between the two pins.<br/>
        /// If useIntelligentConnect is false, this method works only if the two media types are compatible.
        /// </remarks>

        public static void ConnectFilters(IGraphBuilder graphBuilder, IBaseFilter upFilter, string sourcePinName, IBaseFilter downFilter, string destPinName, bool useIntelligentConnect)
        {
            if (graphBuilder.IsNull())
            {
                throw new ArgumentNullException("graphBuilder");
            }

            if (upFilter.IsNull())
            {
                throw new ArgumentNullException("upFilter");
            }

            if (downFilter.IsNull())
            {
                throw new ArgumentNullException("downFilter");
            }

            IPin sourcePin, destPin;

            sourcePin = DsFindPin.ByName(upFilter, sourcePinName);
            if (sourcePin.IsNull())
            {
                throw new ArgumentException("The source filter has no pin called : " + sourcePinName, sourcePinName);
            }

            destPin = DsFindPin.ByName(downFilter, destPinName);
            if (destPin.IsNull())
            {
                throw new ArgumentException("The downstream filter has no pin called : " + destPinName, destPinName);
            }

            try
            {
                ConnectFilters(graphBuilder, sourcePin, destPin, useIntelligentConnect);
            }
            finally
            {
                Marshal.ReleaseComObject(sourcePin);
                Marshal.ReleaseComObject(destPin);
            }
        }
		public static void LoadGraphFile(IGraphBuilder graphBuilder, string fileName)
		{
			int hr = 0;
			IStorage storage = null;
#if USING_NET11
			UCOMIStream stream = null;
#else
			IStream stream = null;
#endif

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			try
			{
				if (NativeMethods.StgIsStorageFile(fileName) != 0)
					throw new ArgumentException();

				hr = NativeMethods.StgOpenStorage(
					fileName,
					null,
					STGM.Transacted | STGM.Read | STGM.ShareDenyWrite,
					IntPtr.Zero,
					0,
					out storage
					);

				Marshal.ThrowExceptionForHR(hr);

				hr = storage.OpenStream(
					@"ActiveMovieGraph",
					IntPtr.Zero,
					STGM.Read | STGM.ShareExclusive,
					0,
					out stream
					);

				Marshal.ThrowExceptionForHR(hr);

				hr = (graphBuilder as IPersistStream).Load(stream);
				Marshal.ThrowExceptionForHR(hr);
			}
			finally
			{
				if (stream.NotNull())
					Marshal.ReleaseComObject(stream);
				if (storage.NotNull())
					Marshal.ReleaseComObject(storage);
			}
		}
		public static void SaveGraphFile(IGraphBuilder graphBuilder, string fileName)
		{
			int hr = 0;
			IStorage storage = null;
#if USING_NET11
			UCOMIStream stream = null;
#else
			IStream stream = null;
#endif

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			try
			{
				hr = NativeMethods.StgCreateDocfile(
					fileName,
					STGM.Create | STGM.Transacted | STGM.ReadWrite | STGM.ShareExclusive,
					0,
					out storage
					);

				Marshal.ThrowExceptionForHR(hr);

				hr = storage.CreateStream(
					@"ActiveMovieGraph",
					STGM.Write | STGM.Create | STGM.ShareExclusive,
					0,
					0,
					out stream
					);

				Marshal.ThrowExceptionForHR(hr);

				hr = (graphBuilder as IPersistStream).Save(stream, true);
				Marshal.ThrowExceptionForHR(hr);

				hr = storage.Commit(STGC.Default);
				Marshal.ThrowExceptionForHR(hr);
			}
			finally
			{
				if (stream.NotNull())
					Marshal.ReleaseComObject(stream);
				if (storage.NotNull())
					Marshal.ReleaseComObject(storage);
			}
		}
		public static void RemoveAllFilters(IGraphBuilder graphBuilder)
		{
			int hr = 0;
			IEnumFilters enumFilters;
			ArrayList filtersArray = new ArrayList();

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			hr = graphBuilder.EnumFilters(out enumFilters);
			DsError.ThrowExceptionForHR(hr);

			try
			{
				IBaseFilter[] filters = new IBaseFilter[1];

				while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
				{
					filtersArray.Add(filters[0]);
				}
			}
			finally
			{
				Marshal.ReleaseComObject(enumFilters);
			}

			foreach (IBaseFilter filter in filtersArray)
			{
				hr = graphBuilder.RemoveFilter(filter);
				Marshal.ReleaseComObject(filter);
			}
		}
		public static void DisconnectAllPins(IGraphBuilder graphBuilder)
		{
			int hr = 0;
			IEnumFilters enumFilters;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			hr = graphBuilder.EnumFilters(out enumFilters);
			DsError.ThrowExceptionForHR(hr);

			try
			{
				IBaseFilter[] filters = new IBaseFilter[1];

				while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
				{
					try
					{
						DisconnectPins(filters[0]);
					}
					catch { }
					Marshal.ReleaseComObject(filters[0]);
				}
			}
			finally
			{
				Marshal.ReleaseComObject(enumFilters);
			}
		}
		public static bool RenderPin(IGraphBuilder graphBuilder, IBaseFilter source, string pinName)
		{
			int hr = 0;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			if (source.IsNull())
				throw new ArgumentNullException("source");

			IPin pin = DsFindPin.ByName(source, pinName);

			if (pin.NotNull())
			{
				hr = graphBuilder.Render(pin);
				Marshal.ReleaseComObject(pin);

				return (hr >= 0);
			}

			return false;
		}
		public static IBaseFilter FindFilterByClsid(IGraphBuilder graphBuilder, Guid filterClsid)
		{
			int hr = 0;
			IBaseFilter filter = null;
			IEnumFilters enumFilters = null;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			hr = graphBuilder.EnumFilters(out enumFilters);
			if (hr == 0)
			{
				IBaseFilter[] filters = new IBaseFilter[1];

				while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
				{
					Guid clsid;

					hr = filters[0].GetClassID(out clsid);

					if ((hr == 0) && (clsid == filterClsid))
					{
						filter = filters[0];
						break;
					}

					Marshal.ReleaseComObject(filters[0]);
				}
				Marshal.ReleaseComObject(enumFilters);
			}

			return filter;
		}
		public static IBaseFilter FindFilterByName(IGraphBuilder graphBuilder, string filterName)
		{
			int hr = 0;
			IBaseFilter filter = null;
			IEnumFilters enumFilters = null;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			hr = graphBuilder.EnumFilters(out enumFilters);
			if (hr == 0)
			{
				IBaseFilter[] filters = new IBaseFilter[1];

				while (enumFilters.Next(filters.Length, filters, IntPtr.Zero) == 0)
				{
					FilterInfo filterInfo;

					hr = filters[0].QueryFilterInfo(out filterInfo);
					if (hr == 0)
					{
						if (filterInfo.pGraph.NotNull())
							Marshal.ReleaseComObject(filterInfo.pGraph);

						if (filterInfo.achName.Equals(filterName))
						{
							filter = filters[0];
							break;
						}
					}

					Marshal.ReleaseComObject(filters[0]);
				}
				Marshal.ReleaseComObject(enumFilters);
			}

			return filter;
		}
		public static IBaseFilter AddFilterByDevicePath(IGraphBuilder graphBuilder, string devicePath, string name)
		{
			int hr = 0;
			IBaseFilter filter = null;
#if USING_NET11
			UCOMIBindCtx bindCtx = null;
			UCOMIMoniker moniker = null;
#else
			IBindCtx bindCtx = null;
			IMoniker moniker = null;
#endif
			int eaten;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			try
			{
				hr = NativeMethods.CreateBindCtx(0, out bindCtx);
				Marshal.ThrowExceptionForHR(hr);

				hr = NativeMethods.MkParseDisplayName(bindCtx, devicePath, out eaten, out moniker);
				Marshal.ThrowExceptionForHR(hr);

				hr = (graphBuilder as IFilterGraph2).AddSourceFilterForMoniker(moniker, bindCtx, name, out filter);
				DsError.ThrowExceptionForHR(hr);
			}
			catch
			{
				// An error occur. Just returning null...
			}
			finally
			{
				if (bindCtx.NotNull()) Marshal.ReleaseComObject(bindCtx);
				if (moniker.NotNull()) Marshal.ReleaseComObject(moniker);
			}

			return filter;
		}
		/// <summary>
		/// Connect pins from two filters
		/// </summary>
		/// <param name="graphBuilder">the IGraphBuilder interface of the graph</param>
		/// <param name="upFilter">the upstream filter</param>
		/// <param name="sourcePinName">the upstream filter pin name</param>
		/// <param name="downFilter">the downstream filter</param>
		/// <param name="destPinName">the downstream filter pin name</param>
		/// <param name="useIntelligentConnect">indicate if the method should use DirectShow's Intelligent Connect</param>
		/// <exception cref="System.ArgumentNullException">Thrown if graphBuilder, upFilter or downFilter are null</exception>
		/// <exception cref="System.ArgumentException">Thrown if pin names are not found in filters</exception>
		/// <exception cref="System.Runtime.InteropServices.COMException">Thrown if pins can't connect</exception>
		/// <remarks>
		/// If useIntelligentConnect is true, this method can add missing filters between the two pins.<br/>
		/// If useIntelligentConnect is false, this method works only if the two media types are compatible.
		/// </remarks>

		public static void ConnectFilters(IGraphBuilder graphBuilder, IBaseFilter upFilter, string sourcePinName, IBaseFilter downFilter, string destPinName, bool useIntelligentConnect)
		{
			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			if (upFilter.IsNull())
				throw new ArgumentNullException("upFilter");

			if (downFilter.IsNull())
				throw new ArgumentNullException("downFilter");

			IPin sourcePin, destPin;

			sourcePin = DsFindPin.ByName(upFilter, sourcePinName);
			if (sourcePin.IsNull())
				throw new ArgumentException("The source filter has no pin called : " + sourcePinName, sourcePinName);

			destPin = DsFindPin.ByName(downFilter, destPinName);
			if (destPin.IsNull())
				throw new ArgumentException("The downstream filter has no pin called : " + destPinName, destPinName);

			try
			{
				ConnectFilters(graphBuilder, sourcePin, destPin, useIntelligentConnect);
			}
			finally
			{
				Marshal.ReleaseComObject(sourcePin);
				Marshal.ReleaseComObject(destPin);
			}
		}
		public static void ConnectFilters(IGraphBuilder graphBuilder, IPin sourcePin, IPin destPin, bool useIntelligentConnect)
		{
			int hr = 0;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			if (sourcePin.IsNull())
				throw new ArgumentNullException("sourcePin");

			if (destPin.IsNull())
				throw new ArgumentNullException("destPin");

			if (useIntelligentConnect)
			{
				hr = graphBuilder.Connect(sourcePin, destPin);
				DsError.ThrowExceptionForHR(hr);
			}
			else
			{
				hr = graphBuilder.ConnectDirect(sourcePin, destPin, null);
				DsError.ThrowExceptionForHR(hr);
			}
		}
		/// <summary>
		/// Add a filter to a DirectShow Graph using its name
		/// </summary>
		/// <param name="graphBuilder">the IGraphBuilder interface of the graph</param>
		/// <param name="deviceCategory">the filter category (see DirectShowLib.FilterCategory)</param>
		/// <param name="friendlyName">the filter name (case-sensitive)</param>
		/// <returns>an instance of the filter if the method successfully created it, null if not</returns>
		/// <example>This sample shows how to programmatically add a NVIDIA Video decoder filter to a graph
		/// <code>
		/// filter = FilterGraphTools.AddFilterByName(graphBuilder, FilterCategory.LegacyAmFilterCategory, "NVIDIA Video Decoder");
		/// </code>
		/// </example>
		/// <exception cref="System.ArgumentNullException">Thrown if graphBuilder is null</exception>
		/// <exception cref="System.Runtime.InteropServices.COMException">Thrown if errors occur when the filter is add to the graph</exception>

		public static IBaseFilter AddFilterByName(IGraphBuilder graphBuilder, Guid deviceCategory, string friendlyName)
		{
			int hr = 0;
			IBaseFilter filter = null;

			if (graphBuilder.IsNull())
				throw new ArgumentNullException("graphBuilder");

			DsDevice[] devices = DsDevice.GetDevicesOfCat(deviceCategory);

			for (int i = 0; i < devices.Length; i++)
			{
				if (!devices[i].Name.Equals(friendlyName))
					continue;

				hr = (graphBuilder as IFilterGraph2).AddSourceFilterForMoniker(devices[i].Mon, null, friendlyName, out filter);
				DsError.ThrowExceptionForHR(hr);

				break;
			}

			return filter;
		}