Martin - you're right, it does look harder than it is. There's a steep (but short) learning curve but once you have the basics down, it will make sense.
Some snippets of code using DirectShow.NET...
A basic graph builder class including code to clean up. I've included two filters to use in the next snippets.
Adding filters to a graph.
Connecting filters.
	
	
	
	
Some snippets of code using DirectShow.NET...
A basic graph builder class including code to clean up. I've included two filters to use in the next snippets.
Code:
public class DvbRadioGraphBuilder : IDisposable
{
    DsROTEntry rot = null;
    IFilterGraph2 graph = null;
    IBaseFilter lameEncoder = null;
    IBaseFilter fileWriter = null;
    ...
    public DvbRadioGraphBuilder(object ParentLog, bool AddToROT)
    {
        graph = (IFilterGraph2) new FilterGraph();
        rot = new DsROTEntry(graph);
    }
    ...
    protected void Decompose()
    {
        int hr = 0;
        try
        {
            // Decompose the graph
            FilterState pfs;
            if (graph != null)
            {
                hr = (graph as DirectShowLib.IMediaControl).GetState(500, out pfs);
                if (pfs != FilterState.Stopped)
                {
                    //
                    // Not sure why I call both StopWhenReady() and Stop()...there must have been a reason
                    //
                    hr = (graph as DirectShowLib.IMediaControl).StopWhenReady();
                    hr = (graph as DirectShowLib.IMediaControl).Stop();
                }
            }
            FilterGraphTools.RemoveAllFilters(graph);
            //
            // Release or dispose of all of the DShow components here
            //
            ...
            if (lameEncoder != null)
            {
                Marshal.ReleaseComObject(lameEncoder);
                lameEncoder = null;
            }
            if (fileWriter != null)
            {
                Marshal.ReleaseComObject(fileWriter);
                fileWriter = null;
            }
            if (rot != null)
            {
                rot.Dispose();
                rot = null;
            }
            if (graph != null)
            {
                Marshal.ReleaseComObject(graph);
                graph = null;
            }
        }
        catch (Exception e)
        {
            // Handle exception
        }
    }
    #region IDisposable Members
    public void Dispose()
    {
        Decompose();
    }
    #endregion
}Code:
private bool AddLAMEEncoderFilter()
    {
        int hr = 0;
        DsDevice[] devices;
        bool FoundLAMEEncoder = false;
        try
        {
            //
            // Get all of the filters normally listed in the "DirectShow Filters" category of GraphEdit
            //
            devices = DsDevice.GetDevicesOfCat(FilterCategory.LegacyAmFilterCategory);
            if (devices.Length == 0)
                Log.WriteLine("No LegacyAmFilterCategory filters found!!!!");
            else
            {
                for (int i = 0; i < devices.Length; i++)
                {
                    try
                    {
                        if (devices[i].Name.Equals("LAME Audio Encoder"))
                        {
                            FoundLAMEEncoder = true;
                            hr = graph.AddSourceFilterForMoniker(devices[i].Mon, null, devices[i].Name, out lameEncoder);
                            DsError.ThrowExceptionForHR(hr);
                            break;
                        }
                    }
                    catch (NullReferenceException e)
                    {
                        // Handle exception
                    }
                }
            }
        }
        catch (Exception e)
        {
            // Handle exception
        }
        return FoundLAMEEncoder;
    }Connecting filters.
Code:
private bool ConnectFiltersForRadio(string RecordingName)
    {
        int hr = 0;
        ...
        IPin pinLameEncOut = null;
        IPin pinFileWriterIn = null;
        bool Success = false;
        try
        {
            IFileSinkFilter2 fs = (IFileSinkFilter2) fileWriter;
            hr = fs.SetMode(AMFileSinkFlags.None);
            DsError.ThrowExceptionForHR(hr);
            hr = fs.SetFileName(RecordingName, null);
            DsError.ThrowExceptionForHR(hr);
            ...
            //
            // The first parameter of FindPin(...) is the actual pin name as shown in GraphEdit
            //
            hr = lameEncoder.FindPin("Out", out pinLameEncOut);
            DsError.ThrowExceptionForHR(hr);
            hr = fileWriter.FindPin("Input", out pinFileWriterIn);
            DsError.ThrowExceptionForHR(hr);
            hr = graph.Connect(pinLameEncOut, pinFileWriterIn);
            DsError.ThrowExceptionForHR(hr);
            Success = true;
        }
        catch (Exception e)
        {
            // Handle exception
        }
        finally
        {
            ...
            if (pinLameEncOut != null)
                Marshal.ReleaseComObject(pinLameEncOut);
            if (pinFileWriterIn != null)
                Marshal.ReleaseComObject(pinFileWriterIn);
        }
        return Success;
    }