Index: mythtv/libs/libmythtv/libmythtv.pro
===================================================================
--- mythtv/libs/libmythtv/libmythtv.pro	(revision 18555)
+++ mythtv/libs/libmythtv/libmythtv.pro	(working copy)
@@ -225,6 +225,10 @@
     HEADERS += profilegroup.h
     SOURCES += profilegroup.cpp
 
+    # Filter wizard stuff
+    HEADERS += filterchaineditor.h
+    SOURCES += filterchaineditor.cpp
+
     # XBox LED control
     HEADERS += xbox.h
     SOURCES += xbox.cpp
Index: mythtv/libs/libmythtv/filterchaineditor.cpp
===================================================================
--- mythtv/libs/libmythtv/filterchaineditor.cpp	(revision 0)
+++ mythtv/libs/libmythtv/filterchaineditor.cpp	(revision 0)
@@ -0,0 +1,552 @@
+#include "filterchaineditor.h"
+#include "filtermanager.h"
+#include "libmyth/mythcontext.h"
+#include <mythtv/libmythui/mythuihelper.h> 
+#include <qlayout.h>
+
+FilterChainEditor::FilterChainEditor(QString chain) : 
+    m_listbox(new ListBoxSetting(this)), m_dialog(NULL), m_redraw(true)
+{
+    addChild(m_listbox);
+    m_listbox->setLabel(QObject::tr("Filter Chain"));
+
+    // Parse the filter string into individual filters
+    m_filterList = QStringList::split(",", chain);
+}
+
+QString FilterChainEditor::exec() 
+{
+    int ret = QDialog::Accepted;
+    m_redraw = true;
+
+    while ((QDialog::Accepted == ret) || m_redraw)
+    {
+        m_redraw = false;
+
+        load();
+
+        m_dialog = new ConfigurationDialogWidget(gContext->GetMainWindow(),
+                                               "FilterChainEditor");
+        connect(m_dialog, SIGNAL(menuButtonPressed()),
+                  this,   SLOT(               open()));
+        connect(m_dialog, SIGNAL(deleteButtonPressed()),
+                  this,   SLOT(         deleteFilter()));
+
+        int   width = 0,    height = 0;
+        float wmult = 0.0f, hmult  = 0.0f;
+        
+        GetMythUI()->GetScreenSettings(width, wmult, height, hmult);
+
+        QVBoxLayout *layout = new QVBoxLayout(m_dialog, (int)(20 * hmult));
+        layout->addWidget(m_listbox->configWidget(NULL, m_dialog));
+
+        m_dialog->Show();
+        ret = m_dialog->exec();
+        
+        m_dialog->deleteLater();
+        m_dialog = NULL;
+
+        if (ret == QDialog::Accepted)
+        {
+            editFilter(m_listbox->getValue().toInt());
+        }
+    }
+    return getFilterString();
+}
+
+void FilterChainEditor::load(void)
+{
+    m_listbox->clearSelections();
+
+    // Fill the listbox with filters in the filter chain
+    int index = 1;
+    for (QStringList::Iterator i = m_filterList.begin(); i != m_filterList.end(); ++i)
+    {
+        m_listbox->addSelection(*i, QString::number(index));
+        index++;
+    }
+    m_listbox->addSelection(QObject::tr("(Add new filter)"), "0");
+
+    if (m_lastSelected < index && m_lastSelected >= 0)
+    {
+        m_listbox->setValue(m_lastSelected);
+    }
+    m_lastSelected = 0;
+}
+
+void FilterChainEditor::open()
+{
+    int id = m_listbox->getValue().toInt();
+    if (id != 0)
+    {
+        // Prompt user for action
+        QStringList buttons;
+        buttons << QObject::tr("Move Up");
+        buttons << QObject::tr("Move Down");
+        buttons << QObject::tr("Remove");
+        buttons << QObject::tr("Cancel");
+        int value = MythPopupBox::ShowButtonPopup(gContext->GetMainWindow(),
+                                         "", QObject::tr("Filter Options"),
+                                         buttons, kDialogCodeButton3);
+        if (value == 0)
+        {
+            raiseFilter();   // Move the filter up in the chain
+        }
+        else if (value == 1)
+        {
+            lowerFilter();   // Move the filter down in the chain
+        }
+        else if (value == 2)
+        {
+            deleteFilter();  // Remove the filter from the chain
+        }
+    }
+}
+
+void FilterChainEditor::deleteFilter()
+{
+    int id = m_listbox->getValue().toInt();
+    if (id == 0)
+    {
+        return;
+    }
+
+    // Prompt user for confirmation
+    int value = MythPopupBox::Show2ButtonPopup(gContext->GetMainWindow(),"",
+                                     QObject::tr("Delete filter?"), 
+                                     QObject::tr("Yes, delete filter"),
+                                     QObject::tr("No, Don't delete filter"), kDialogCodeButton2);
+    if (value == 0)
+    {
+        m_filterList.removeAt(id - 1);
+        m_redraw = true;
+        if (m_dialog)
+        {
+            m_dialog->done(QDialog::Rejected);
+        }
+    }
+}
+
+void FilterChainEditor::editFilter(int id)
+{
+    if (id != 0)
+    {
+        m_lastSelected = id - 1;
+        QString filterName = m_filterList.at(id - 1).section('=', 0, 0);
+        const FilterInfo* info = m_manager.GetFilterInfo(filterName);
+        if (info)
+        {
+            QStringList parameters = QStringList::split(",", info->params);
+            if (parameters.size() > 0)
+            {
+                // Edit the filters parameters
+                FilterWizard filterwizard(filterName);
+                filterwizard.loadByString(m_filterList.at(id - 1).section('=', 1));
+                if (filterwizard.exec(false) == QDialog::Accepted)
+                {
+                    filterwizard.Save();
+                    m_filterList.replace(id - 1, filterwizard.getString());
+                }
+            }
+        }
+    }
+    else
+    {
+        // Allow user to choose which type of filter to add
+        FilterSelector selector;
+        selector.exec();
+        if (selector.getString() != "")
+        {
+            m_filterList.append(selector.getString());
+        }
+    }
+}
+
+void FilterChainEditor::raiseFilter()
+{
+    int id = m_listbox->getValue().toInt() - 1;
+    if (id <= 0)
+    {
+        return;
+    }
+        
+    m_lastSelected = id - 1;
+    m_filterList.swap(id - 1, id);
+    m_redraw = true;
+    
+    if (m_dialog)
+    {
+        m_dialog->done(QDialog::Rejected);
+    }
+}
+
+void FilterChainEditor::lowerFilter()
+{
+    int id = m_listbox->getValue().toInt() - 1;
+    if (id >= (int)m_filterList.size() - 1)
+    {
+        return;
+    }
+        
+    m_lastSelected = id + 1;
+    m_filterList.swap(id, id + 1);
+    m_redraw = true;
+    
+    if (m_dialog)
+    {
+        m_dialog->done(QDialog::Rejected);
+    }
+}
+
+QString FilterChainEditor::getFilterString()
+{
+    // Concatenate all the filters together with commas
+    QStringListIterator iter(m_filterList);
+    QString filterstring = "";
+    bool hasFirst = false;
+    while (iter.hasNext())
+    {
+       if (hasFirst)
+       {
+          filterstring.append(",");
+       }
+       hasFirst = true;
+       filterstring.append(iter.next());
+    }
+
+    return filterstring;
+}
+
+FilterSelector::FilterSelector() : m_listbox(new FilterListBox(this)),
+    m_help(new TransLabelSetting()), m_dialog(NULL), m_redraw(true)
+{
+    addChild(m_listbox);
+    addChild(m_help);
+    m_listbox->setLabel(QObject::tr("Filters"));
+}
+
+int FilterSelector::exec() 
+{
+    int ret = QDialog::Accepted;
+    m_redraw = true;
+
+    while ((QDialog::Accepted == ret) || m_redraw)
+    {
+        m_redraw = false;
+
+        load();
+
+        m_dialog = new ConfigurationDialogWidget(gContext->GetMainWindow(),
+                                               "FilterSelector");
+
+        int   width = 0,    height = 0;
+        float wmult = 0.0f, hmult  = 0.0f;
+        GetMythUI()->GetScreenSettings(width, wmult, height, hmult);
+
+        QVBoxLayout *layout = new QVBoxLayout(m_dialog, (int)(20 * hmult));
+        layout->addWidget(m_listbox->configWidget(NULL, m_dialog));
+        layout->addWidget(m_help->configWidget(NULL, m_dialog));
+
+        connect(m_listbox, SIGNAL(highlighted(int)),
+                this,      SLOT(  setHelpText(int)));
+        m_dialog->Show();
+        ret = m_dialog->exec();
+        m_dialog->deleteLater();
+        m_dialog = NULL;
+
+        if (ret == QDialog::Accepted)
+        {
+            if (open(m_listbox->getSelectionLabel()) == QDialog::Accepted)
+            {
+                return ret;
+            }
+        }
+    }
+
+    return QDialog::Rejected;
+}
+
+void FilterSelector::load(void) 
+{
+    m_listbox->clearSelections();
+
+    // Get the list of the available filters on the system
+    filter_map_t info = m_manager.GetAllFilterInfo();
+    filter_map_t::iterator iter;
+
+    for (iter = info.begin(); iter != info.end(); ++iter)
+    {
+        m_listbox->addSelection(iter->second->name);
+    }
+    
+    m_listbox->setValue(0);
+    setHelpText(0);
+}
+
+void FilterSelector::setHelpText(int id)
+{
+    const FilterInfo* info = m_manager.GetFilterInfo(m_listbox->getSelectionLabel());
+    m_help->setValue(info->descript);
+}
+
+int FilterSelector::open(QString filterName)
+{
+    const FilterInfo* info = m_manager.GetFilterInfo(filterName);
+    
+    QString params(info->params);
+    if (!params.isNull() && !params.isEmpty())
+    {
+        QStringList parameters = QStringList::split(",", params);
+        FilterWizard filterwizard(filterName);
+        if (filterwizard.exec(false) == QDialog::Accepted)
+        {
+            filterwizard.Save();
+            m_filterstring = filterwizard.getString();
+            return QDialog::Accepted;
+        }
+        return QDialog::Rejected;
+    }
+    m_filterstring = filterName;
+    return QDialog::Accepted;
+}
+
+QWidget* FilterListBox::configWidget(ConfigurationGroup *cg, QWidget* parent, 
+                                  const char* widgetName)
+{
+    QWidget* box = ListBoxSetting::configWidget(cg,parent,widgetName);
+
+    connect(widget, SIGNAL(highlighted(int)),
+            this,   SIGNAL(highlighted(int)));
+
+    return box;
+}
+
+FilterWizard::FilterWizard(QString name)
+{
+    m_name = name;
+    m_hasDisable = false;
+    m_config = new VerticalConfigurationGroup(false);
+    m_config->setLabel("Filters->" + m_name);
+
+    FilterManager manager;
+    const FilterInfo* info = manager.GetFilterInfo(m_name);
+    QStringList parameters = QStringList::split(",", info->params);
+
+    // Create a widget for each parameter
+    QStringListIterator iter(parameters);
+    while(iter.hasNext())
+    {
+        QStringList description = QStringList::split(":", iter.next());
+        if (description.size() == 3 && description[0] == "disable")
+        {
+            // The disable parameter is special and overrides all the other
+            // parameters.  If the filter is disabled then none of the 
+            // other parameters will be stored.
+            m_disableBox = new DisableFilterParam(description);
+            m_config->addChild(m_disableBox);
+            m_hasDisable = true;
+        }
+        else
+        {
+            QString* store = new QString("");
+            if (description.count() == 6 && description[0] == "int")
+            {
+                IntegerFilterParam* param = new IntegerFilterParam(description, store);
+                m_config->addChild(param);
+                m_values.append(store);
+            }
+            else if (description.size() == 6 && description[0] == "float")
+            {
+                FloatFilterParam* param = new FloatFilterParam(description, store);
+                m_config->addChild(param);
+                m_values.append(store);
+            }
+            else if (description.size() == 5 && description[0] == "flag")
+            {
+                BooleanFilterParam* param = new BooleanFilterParam(description, store);
+                m_config->addChild(param);
+                m_values.append(store);
+            }
+            else
+            {
+               delete store;
+            }
+        }
+    }
+    addChild(m_config);
+}
+
+FilterWizard::~FilterWizard()
+{
+    QListIterator<QString*> values(m_values);
+    while (values.hasNext())
+    {
+        delete values.next();
+    }
+}
+
+void FilterWizard::loadByString(QString params)
+{
+    // Split the existing filter string into individual parameter values
+    QStringList parameters = QStringList::split(":", params);
+
+    // If the filter is disabled don't look for the rest of the parameters in
+    // the string.
+    if (m_hasDisable && parameters.count() == 1 && parameters[0] == m_disableBox->getFlag())
+    {
+        m_disableBox->setValue(true);
+    }
+    else
+    {
+        for (int i = 0; i < parameters.count() && i < m_values.count(); i++)
+        {
+            m_values.value(i)->truncate(0);
+            m_values.value(i)->append(parameters[i]);
+        }
+    }
+    m_config->Load();
+}
+
+QString FilterWizard::getString()
+{
+    // Construct a filter parameter string from the widget values
+    QString filterstring = m_name;
+    QString parameters = "";
+
+    // If the filter is disabled don't output any other parameters
+    if (m_hasDisable && m_disableBox->boolValue() == true)
+    {
+        parameters = m_disableBox->getFlag();
+    }
+    else
+    {
+        bool hasFirst = false;
+        QListIterator<QString*> values(m_values);
+        while (values.hasNext())
+        {
+           QString* value = values.next();
+           if (!value->isNull() && !value->isEmpty())
+           {
+              if (hasFirst)
+              {
+                 parameters.append(":");
+              }
+              hasFirst = true;
+              parameters.append(*value);
+           }
+        }
+    }
+    if (parameters.stripWhiteSpace() != "")
+    {
+        filterstring.append("=" + parameters);
+    }
+    
+    return filterstring;
+}
+
+FilterWizard::IntegerFilterParam::IntegerFilterParam(QStringList info, QString* store) :
+    SliderSetting::SliderSetting(this,0,255,1), stringVal(store)
+{
+    if (info.count() == 6)
+    {
+        min = info[3].toInt();
+        max = info[4].toInt();
+
+        setName(info[1]);
+        setLabel(info[1]);
+        setHelpText(info[2]);
+
+        setValue(info[5].toInt());
+        stringVal->append(info[5]);
+    }
+}
+
+void FilterWizard::IntegerFilterParam::Save()
+{
+    stringVal->truncate(0);
+    stringVal->append(getValue());
+}
+
+FilterWizard::FloatFilterParam::FloatFilterParam(QStringList info, QString* store) :
+    SliderSetting::SliderSetting(this,0,100,1), stringVal(store)
+{
+    if (info.count() == 6)
+    {
+        min = info[3].toFloat() >= 0 ? int(info[3].toFloat() * 100.0 + .1) :
+                                       int(info[3].toFloat() * 100.0 - .1);
+        max = info[4].toFloat() >= 0 ? int(info[4].toFloat() * 100.0 + .1) :
+                                       int(info[4].toFloat() * 100.0 - .1 );
+
+        setName(info[1]);
+        setLabel(info[1]);
+        setHelpText(info[2]);
+
+        int defVal = info[5].toFloat() >= 0 ? int(info[5].toFloat() * 100.0 + .1) :
+                                              int(info[5].toFloat() * 100.0 - .1);
+        setValue(defVal);
+        stringVal->append(info[5]);
+    }
+}
+
+void FilterWizard::FloatFilterParam::Load()
+{
+     setValue(stringVal->toFloat() >= 0 ? int(stringVal->toFloat() * 100.0 + .1) :
+                                            int(stringVal->toFloat() * 100.0 - .1));
+}
+
+void FilterWizard::FloatFilterParam::Save()
+{
+    stringVal->truncate(0);
+    stringVal->append(QString::number((float)(getValue().toInt()) / 100.0,'f',2));
+}
+
+FilterWizard::BooleanFilterParam::BooleanFilterParam(QStringList info, QString* store) :
+    CheckBoxSetting::CheckBoxSetting(this), stringVal(store)
+{
+    if (info.count() == 5)
+    {
+        setName(info[1]);
+        setLabel(info[1]);
+        setHelpText(info[2]);
+
+        flag = info[3];
+        if (info[4] == "on")
+        {
+           setValue(true);
+           stringVal->append(flag);
+        }
+        else
+        {
+           setValue(false);
+        }
+        setEnabled(true);
+    }
+}
+
+void FilterWizard::BooleanFilterParam::Save()
+{
+    stringVal->truncate(0);
+    stringVal->append(boolValue() ? flag : "");
+}
+
+FilterWizard::DisableFilterParam::DisableFilterParam(QStringList info) :
+    CheckBoxSetting::CheckBoxSetting(this)
+{
+    if (info.count() == 3)
+    {
+        setName(info[0]);
+        setLabel(info[0]);
+        setHelpText(QObject::tr("Disable the filter."));
+
+        flag = info[1];
+        if (info[2] == "yes")
+        {
+           setValue(true);
+        }
+        else
+        {
+           setValue(false);
+        }
+        setEnabled(true);
+    }
+}
Index: mythtv/libs/libmythtv/filter.h
===================================================================
--- mythtv/libs/libmythtv/filter.h	(revision 18555)
+++ mythtv/libs/libmythtv/filter.h	(working copy)
@@ -26,6 +26,7 @@
     char *descript;
     FmtConv *formats;
     char *libname;
+    char *params;
 } FilterInfo;
 
 typedef struct  VideoFilter_
Index: mythtv/libs/libmythtv/filtermanager.cpp
===================================================================
--- mythtv/libs/libmythtv/filtermanager.cpp	(revision 18555)
+++ mythtv/libs/libmythtv/filtermanager.cpp	(working copy)
@@ -105,6 +105,7 @@
         free(tmp->name);
         free(tmp->descript);
         free(tmp->libname);
+        free(tmp->params);
         delete [] (tmp->formats);
         delete tmp;
     }
@@ -161,6 +162,7 @@
         newFilter->symbol   = strdup(filtInfo->symbol);
         newFilter->name     = strdup(filtInfo->name);
         newFilter->descript = strdup(filtInfo->descript);
+        newFilter->params   = strdup(filtInfo->params);
 
         int i = 0;
         for (; filtInfo->formats[i].in != FMT_NONE; i++);
Index: mythtv/libs/libmythtv/recordingprofile.h
===================================================================
--- mythtv/libs/libmythtv/recordingprofile.h	(revision 18555)
+++ mythtv/libs/libmythtv/recordingprofile.h	(working copy)
@@ -116,6 +116,7 @@
     void ResizeTranscode(bool resize); 
     void SetLosslessTranscode(bool lossless);
     void FiltersChanged(const QString &val);
+    void EditFilters();
 
   private:
     ID                       *id;
Index: mythtv/libs/libmythtv/channelsettings.cpp
===================================================================
--- mythtv/libs/libmythtv/channelsettings.cpp	(revision 18555)
+++ mythtv/libs/libmythtv/channelsettings.cpp	(working copy)
@@ -1,6 +1,7 @@
 #include "channelsettings.h"
 #include "cardutil.h"
 #include "channelutil.h"
+#include "filterchaineditor.h"
 
 QString ChannelDBStorage::GetWhereClause(MSqlBindings &bindings) const
 {
@@ -196,11 +197,11 @@
     }
 };
 
-class VideoFilters : public LineEditSetting, public ChannelDBStorage
+class VideoFilterButton : public ButtonSetting, public ChannelDBStorage
 {
   public:
-    VideoFilters(const ChannelID &id) :
-        LineEditSetting(this), ChannelDBStorage(this, id, "videofilters")
+    VideoFilterButton(const ChannelID &id) :
+        ButtonSetting(this), ChannelDBStorage(this, id, "videofilters")
     {
         setLabel(QObject::tr("Video filters"));
         setHelpText(QObject::tr("Filters to be used when recording "
@@ -211,11 +212,11 @@
 };
 
 
-class OutputFilters : public LineEditSetting, public ChannelDBStorage
+class OutputFilterButton : public ButtonSetting, public ChannelDBStorage
 {
   public:
-    OutputFilters(const ChannelID &id) :
-        LineEditSetting(this), ChannelDBStorage(this, id, "outputfilters")
+    OutputFilterButton(const ChannelID &id) :
+        ButtonSetting(this), ChannelDBStorage(this, id, "outputfilters")
     {
         setLabel(QObject::tr("Playback filters"));
         setHelpText(QObject::tr("Filters to be used when recordings "
@@ -468,10 +469,30 @@
     setLabel(QObject::tr("Channel Options - Filters"));
     setUseLabel(false);
 
-    addChild(new VideoFilters(id));
-    addChild(new OutputFilters(id));
+    videoButton = new VideoFilterButton(id);
+    outputButton = new OutputFilterButton(id);
+
+    addChild(videoButton);
+    addChild(outputButton);
+
+    connect(videoButton,  SIGNAL(   pressed()),
+            this,         SLOT(videoPressed()));
+    connect(outputButton, SIGNAL(    pressed()),
+            this,         SLOT(outputPressed()));
 }
 
+void ChannelOptionsFilters::videoPressed()
+{
+    FilterChainEditor editor(videoButton->getValue());
+    videoButton->setValue(editor.exec());
+}
+
+void ChannelOptionsFilters::outputPressed()
+{
+    FilterChainEditor editor(outputButton->getValue());
+    outputButton->setValue(editor.exec());
+}
+
 ChannelOptionsV4L::ChannelOptionsV4L(const ChannelID& id) :
     VerticalConfigurationGroup(false, true, false, false)
 {
Index: mythtv/libs/libmythtv/filterchaineditor.h
===================================================================
--- mythtv/libs/libmythtv/filterchaineditor.h	(revision 0)
+++ mythtv/libs/libmythtv/filterchaineditor.h	(revision 0)
@@ -0,0 +1,124 @@
+#ifndef FILTERCHAINEDITOR_H
+#define FILTERCHAINEDITOR_H
+
+#include "libmyth/settings.h"
+#include "libmyth/mythwidgets.h"
+#include "filtermanager.h"
+
+class FilterWizard : public ConfigurationWizard
+{
+protected:
+  class IntegerFilterParam : public SliderSetting, public TransientStorage
+  {
+  public:
+    IntegerFilterParam(QStringList info, QString* store);
+    void Load() {settingValue = *stringVal;}
+    void Save();
+  protected:
+    QString* stringVal; // The stored value
+  };
+
+  class FloatFilterParam : public SliderSetting, public TransientStorage
+  {
+    public:
+      FloatFilterParam(QStringList info, QString* store);
+      void Load();
+      void Save();
+    protected:
+      QString* stringVal; // The stored value
+  };
+
+  class BooleanFilterParam : public CheckBoxSetting, public TransientStorage
+  {
+    public:
+      BooleanFilterParam(QStringList info, QString* store);
+      void Load() {setValue(stringVal->compare(flag) == 0);}
+      void Save();
+    protected:
+      QString  flag;      // The enabled flag
+      QString* stringVal; // The stored value
+  };
+
+  class DisableFilterParam : public CheckBoxSetting, public TransientStorage
+  {
+  public:
+    DisableFilterParam(QStringList info);
+    QString getFlag(){return flag;}
+  protected:
+    QString flag; // The enabled flag
+  };
+
+  VerticalConfigurationGroup *m_config;
+  DisableFilterParam         *m_disableBox;
+  bool                        m_hasDisable; // If this filter can be disabled
+  QList<QString*>             m_values;     // List of the stored values
+  QString                     m_name;       // Filter name
+
+public:
+  FilterWizard(QString name);
+  ~FilterWizard();
+  void loadByString(QString params);
+  QString getString();
+};
+
+class FilterListBox : public ListBoxSetting
+{
+Q_OBJECT
+public:
+  FilterListBox(Storage *_storage) : ListBoxSetting(_storage){}
+  virtual QWidget* configWidget(ConfigurationGroup *cg, QWidget* parent,
+                                  const char* widgetName = 0);
+signals:
+  void highlighted(int);
+};
+
+class MPUBLIC FilterSelector : public QObject, public ConfigurationDialog
+{
+Q_OBJECT
+public:
+  FilterSelector();
+  QString getString(){return m_filterstring;}
+  virtual int exec();
+  virtual void load();
+  virtual void save(){};
+
+protected slots:
+  int open(QString filterName);
+  void setHelpText(int id);
+
+protected:
+  FilterManager      m_manager;      // Gets info on available filters
+  QString            m_filterstring; // [[<filter>=<options>,]...]
+  FilterListBox     *m_listbox;
+  TransLabelSetting *m_help;
+  MythDialog        *m_dialog;
+  bool               m_redraw;
+};
+
+class MPUBLIC FilterChainEditor : public QObject, public ConfigurationDialog
+{
+Q_OBJECT
+public:
+  FilterChainEditor(QString chain);
+  virtual QString exec();
+  virtual void load();
+  virtual void save(){};
+
+protected slots:
+  void open();
+  void deleteFilter();            // Remove filter from the chain
+
+protected:
+  void raiseFilter();             // Move filter forward in the chain
+  void lowerFilter();             // Move filter backward in the chain
+  void editFilter(int id);        // Modify filter paramters
+  QString getFilterString();      // Return a comma delineated filter list
+  FilterManager   m_manager;      // Gets info on available filters
+  QStringList     m_filterList;   // list of [[<filter>=<options>,]...]
+  ListBoxSetting *m_listbox;
+  MythDialog     *m_dialog;
+  int             m_lastSelected;
+  bool            m_redraw;
+};
+
+#endif 
Index: mythtv/libs/libmythtv/filtermanager.h
===================================================================
--- mythtv/libs/libmythtv/filtermanager.h	(revision 18555)
+++ mythtv/libs/libmythtv/filtermanager.h	(working copy)
@@ -45,10 +45,16 @@
                              VideoFrameType &outpixfmt, int &width,
                              int &height, int &bufsize);
 
+    const FilterInfo *GetFilterInfo(const QString &name) const;
+    
+    filter_map_t GetAllFilterInfo() 
+    {
+      return filter_map_t(filters); 
+    } 
+    
   private:
     bool LoadFilterLib(const QString &path);
-    const FilterInfo *GetFilterInfo(const QString &name) const;
-
+    
     library_map_t dlhandles;
     filter_map_t  filters;
 };
Index: mythtv/libs/libmythtv/recordingprofile.cpp
===================================================================
--- mythtv/libs/libmythtv/recordingprofile.cpp	(revision 18555)
+++ mythtv/libs/libmythtv/recordingprofile.cpp	(working copy)
@@ -4,6 +4,7 @@
 #include <QLayout>
 
 #include "recordingprofile.h"
+#include "filterchaineditor.h"
 #include "cardutil.h"
 #include "libmyth/mythcontext.h"
 #include "libmythdb/mythdb.h"
@@ -994,18 +995,17 @@
     };
 };
 
-class TranscodeFilters : public LineEditSetting, public CodecParamStorage
+class TranscodeFilters : public ButtonSetting, public CodecParamStorage
 {
   public:
     TranscodeFilters(const RecordingProfile &parent) :
-        LineEditSetting(this),
+        ButtonSetting(this),
         CodecParamStorage(this, parent, "transcodefilters")
     {
         setLabel(QObject::tr("Custom Filters"));
         setHelpText(QObject::tr("Filters used when transcoding with this "
                                 "profile. This value must be blank to perform "
-                                "lossless transcoding.  Format: "
-                                "[[<filter>=<options>,]...]"
+                                "lossless transcoding."
                                 ));
     };
 };
@@ -1273,6 +1273,8 @@
                     this,        SLOT(  SetLosslessTranscode(bool)));
             connect(tr_filters,  SIGNAL(valueChanged(const QString&)),
                     this,        SLOT(FiltersChanged(const QString&)));
+            connect(tr_filters,  SIGNAL(pressed  ()),
+                    this,        SLOT(EditFilters()));
         }
     }
     else if (type.toUpper() == "DVB")
@@ -1284,6 +1286,12 @@
     Load();
 }
 
+void RecordingProfile::EditFilters()
+{
+    FilterChainEditor editor(tr_filters->getValue());
+    tr_filters->setValue(editor.exec());
+}
+
 void RecordingProfile::FiltersChanged(const QString &val)
 {
     if (!tr_filters || !tr_lossless)
Index: mythtv/libs/libmythtv/channelsettings.h
===================================================================
--- mythtv/libs/libmythtv/channelsettings.h	(revision 18555)
+++ mythtv/libs/libmythtv/channelsettings.h	(working copy)
@@ -105,6 +105,8 @@
 
 class OnAirGuide;
 class XmltvID;
+class VideoFilterButton;
+class OutputFilterButton;
 
 class ChannelOptionsCommon: public VerticalConfigurationGroup
 {
@@ -124,8 +126,15 @@
 };
 
 class ChannelOptionsFilters: public VerticalConfigurationGroup {
+Q_OBJECT
 public:
     ChannelOptionsFilters(const ChannelID& id);
+public slots:
+    void outputPressed();
+    void videoPressed();
+protected:
+    VideoFilterButton  *videoButton;
+    OutputFilterButton *outputButton;
 };
 
 class ChannelOptionsV4L: public VerticalConfigurationGroup {
Index: mythtv/filters/linearblend/filter_linearblend.c
===================================================================
--- mythtv/filters/linearblend/filter_linearblend.c	(revision 18555)
+++ mythtv/filters/linearblend/filter_linearblend.c	(working copy)
@@ -380,7 +380,8 @@
         name:       "linearblend",
         descript:   "fast blending deinterlace filter",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     ""
     },
     FILT_NULL
 };
Index: mythtv/filters/quickdnr/filter_quickdnr.c
===================================================================
--- mythtv/filters/quickdnr/filter_quickdnr.c	(revision 18555)
+++ mythtv/filters/quickdnr/filter_quickdnr.c	(working copy)
@@ -586,7 +586,8 @@
         name:       "quickdnr",
         descript:   "removes noise with a fast single/double thresholded average filter",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     "int:threshold:Less to more filtering.:0:255:0"
     },
     FILT_NULL
 };
Index: mythtv/filters/postprocess/filter_postprocess.c
===================================================================
--- mythtv/filters/postprocess/filter_postprocess.c	(revision 18555)
+++ mythtv/filters/postprocess/filter_postprocess.c	(working copy)
@@ -133,7 +133,8 @@
         name:       "postprocess",
         descript:   "FFMPEG's postprocessing filters",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     ""
     },
     FILT_NULL
 };
Index: mythtv/filters/onefield/filter_onefield.c
===================================================================
--- mythtv/filters/onefield/filter_onefield.c	(revision 18555)
+++ mythtv/filters/onefield/filter_onefield.c	(working copy)
@@ -101,9 +101,10 @@
     {
         symbol:     "new_filter",
         name:       "onefield",
-        descript:   "one-field-only deinterlace filter; parameter \"bottom\" for bottom field, otherwise top",
+        descript:   "one-field-only deinterlace filter",
         formats:    FmtList,
         libname:    NULL,
+        params:     "flag:keep bottom field:Keep the bottom field instead of the top one.:bottom:off"
     },
     FILT_NULL
 };
Index: mythtv/filters/bobdeint/filter_bobdeint.c
===================================================================
--- mythtv/filters/bobdeint/filter_bobdeint.c	(revision 18555)
+++ mythtv/filters/bobdeint/filter_bobdeint.c	(working copy)
@@ -150,6 +150,7 @@
         descript:   "bob deinterlace filter; splits fields to top and bottom of buffer",
         formats:    FmtList,
         libname:    NULL,
+        params:     ""
     },
     FILT_NULL
 };
Index: mythtv/filters/adjust/filter_adjust.c
===================================================================
--- mythtv/filters/adjust/filter_adjust.c	(revision 18555)
+++ mythtv/filters/adjust/filter_adjust.c	(working copy)
@@ -313,7 +313,14 @@
         name:       "adjust",
         descript:   "adjust range and gamma of video",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     "disable:-1:no,"
+                    "int:minimum luma:Minimum luma input value.:0:255:16,"
+                    "int:maximum luma:Maximum luma input value.:0:255:253,"
+                    "float:luma gamma:Luma gamma correction.:0:1:1,"
+                    "int:minimum chroma:Minimum chroma input value.:0:255:2,"
+                    "int:maximum chroma:Maximum chroma input value.:0:255:253,"
+                    "float:chroma gamma:Chroma gamma correction.:0:1:1"
     },
     FILT_NULL
 };
Index: mythtv/filters/yadif/filter_yadif.c
===================================================================
--- mythtv/filters/yadif/filter_yadif.c	(revision 18555)
+++ mythtv/filters/yadif/filter_yadif.c	(working copy)
@@ -592,14 +592,16 @@
             name:       "yadifdeint",
             descript:   "combines data from several fields to deinterlace with less motion blur",
             formats:    FmtList,
-            libname:    NULL
+            libname:    NULL,
+            params:     ""
     },
     {
 symbol:     "YadifDeintFilter",
             name:       "yadifdoubleprocessdeint",
             descript:   "combines data from several fields to deinterlace with less motion blur",
             formats:    FmtList,
-            libname:    NULL
+            libname:    NULL,
+            params:     ""
     },FILT_NULL
 };
 
Index: mythtv/filters/force/filter_force.c
===================================================================
--- mythtv/filters/force/filter_force.c	(revision 18555)
+++ mythtv/filters/force/filter_force.c	(working copy)
@@ -101,28 +101,32 @@
         name:       "forceyv12",
         descript:   "forces use of YV12 video format",
         formats:    Fmt_List_YV12,
-        libname:    NULL
+        libname:    NULL,
+        params:     "" 
     },
     {
         symbol:     "new_force_yuv422p",
         name:       "forceyuv422p",
         descript:   "forces use of YUV422P video format",
         formats:    Fmt_List_YUV422P,
-        libname:    NULL
+        libname:    NULL,
+        params:     "" 
     },
     {
         symbol:     "new_force_rgb24",
         name:       "forcergb24",
         descript:   "forces use of RGB24 video format",
         formats:    Fmt_List_RGB24,
-        libname:    NULL
+        libname:    NULL,
+        params:     "" 
     },
     {
         symbol:     "new_force_argb32",
         name:       "forceargb32",
         descript:   "forces use of ARGB32 video format",
         formats:    Fmt_List_ARGB32,
-        libname:    NULL
+        libname:    NULL,
+        params:     "" 
     },
     FILT_NULL
 };
Index: mythtv/filters/crop/filter_crop.c
===================================================================
--- mythtv/filters/crop/filter_crop.c	(revision 18555)
+++ mythtv/filters/crop/filter_crop.c	(working copy)
@@ -301,7 +301,11 @@
         name:       "crop",
         descript:   "crops picture by macroblock intervals",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     "int:top:Amount to crop on top as number of 16 pixel blocks.:0:255:1,"
+                    "int:left:Amount to crop on left as number of 16 pixel blocks.:0:255:1,"
+                    "int:bottom:Amount to crop on bottom as number of 16 pixel blocks.:0:255:1,"
+                    "int:right:Amount to crop on right as number of 16 pixel blocks.:0:255:1"
     },
     FILT_NULL
 };
Index: mythtv/filters/kerneldeint/filter_kerneldeint.c
===================================================================
--- mythtv/filters/kerneldeint/filter_kerneldeint.c	(revision 18555)
+++ mythtv/filters/kerneldeint/filter_kerneldeint.c	(working copy)
@@ -370,7 +370,9 @@
         name:       "kerneldeint",
         descript:   "combines data from several fields to deinterlace with less motion blur",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     "int:threshold:Adjacent lines differing by more than the threshold value are filtered.:0:255:10,"
+                    "flag:skip chroma:If enabled only luminance will be filtered.:1:off"
     },
     FILT_NULL
 };
Index: mythtv/filters/ivtc/filter_ivtc.c
===================================================================
--- mythtv/filters/ivtc/filter_ivtc.c	(revision 18555)
+++ mythtv/filters/ivtc/filter_ivtc.c	(working copy)
@@ -252,7 +252,8 @@
         name:       "ivtc",
         descript:   "inverse telecine filter",
         formats:    FmtList,
-        libname:    NULL    
+        libname:    NULL,
+        params:     ""
     },
     FILT_NULL
 };
Index: mythtv/filters/invert/filter_invert.c
===================================================================
--- mythtv/filters/invert/filter_invert.c	(revision 18555)
+++ mythtv/filters/invert/filter_invert.c	(working copy)
@@ -79,7 +79,8 @@
         name:       "invert",
         descript:   "inverts the colors of the input video",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     ""
     },
     FILT_NULL
 };
Index: mythtv/filters/greedyhdeint/filter_greedyhdeint.c
===================================================================
--- mythtv/filters/greedyhdeint/filter_greedyhdeint.c	(revision 18555)
+++ mythtv/filters/greedyhdeint/filter_greedyhdeint.c	(working copy)
@@ -333,14 +333,16 @@
             name:       "greedyhdeint",
             descript:   "combines data from several fields to deinterlace with less motion blur",
             formats:    FmtList,
-            libname:    NULL
+            libname:    NULL,
+            params:     ""
     },
     {
 symbol:     "GreedyHDeintFilter",
             name:       "greedyhdoubleprocessdeint",
             descript:   "combines data from several fields to deinterlace with less motion blur",
             formats:    FmtList,
-            libname:    NULL
+            libname:    NULL,
+            params:     ""
     },FILT_NULL
 };
 
Index: mythtv/filters/denoise3d/filter_denoise3d.c
===================================================================
--- mythtv/filters/denoise3d/filter_denoise3d.c	(revision 18555)
+++ mythtv/filters/denoise3d/filter_denoise3d.c	(working copy)
@@ -474,7 +474,10 @@
         name:       "denoise3d",
         descript:   "removes noise with a spatial and temporal low-pass filter",
         formats:    FmtList,
-        libname:    NULL
+        libname:    NULL,
+        params:     "float:luma spatial filter strength:Luma spatial filter strength.:0:1:0,"
+                    "float:chroma spatial filter strength:Chroma spatial filter strength.:0:1:0,"
+                    "float:luma temporal filter strength:Luma temporal filter strength.:0:1:0"
     },
     FILT_NULL
 };
