diff --git a/mythtv/libs/libmyth/libmyth.pro b/mythtv/libs/libmyth/libmyth.pro
index bde661a..5b93129 100644
--- a/mythtv/libs/libmyth/libmyth.pro
+++ b/mythtv/libs/libmyth/libmyth.pro
@@ -68,6 +68,9 @@ SOURCES += mythrssmanager.cpp     netgrabbermanager.cpp
 SOURCES += rssparse.cpp           netutils.cpp
 SOURCES += filesysteminfo.cpp
 
+HEADERS += playsettings.h
+SOURCES += playsettings.cpp
+
 # remove when everything is switched to mythui
 SOURCES += virtualkeyboard_qt.cpp
 
diff --git a/mythtv/libs/libmyth/mythconfiggroups.cpp b/mythtv/libs/libmyth/mythconfiggroups.cpp
index 648c810..04bd5ca 100644
--- a/mythtv/libs/libmyth/mythconfiggroups.cpp
+++ b/mythtv/libs/libmyth/mythconfiggroups.cpp
@@ -476,6 +476,7 @@ void TriggeredConfigurationGroup::addTarget(QString triggerValue,
                                             Configurable *target)
 {
     VerifyLayout();
+    bool isDuplicate = triggerMap.values().contains(target);
     triggerMap[triggerValue] = target;
 
     if (!configStack)
@@ -485,7 +486,10 @@ void TriggeredConfigurationGroup::addTarget(QString triggerValue,
         configStack->setSaveAll(isSaveAll);
     }
 
-    configStack->addChild(target);
+    // Don't add a target as a child if it has already been added,
+    // otherwise something goes wrong with signals in the child.
+    if (!isDuplicate)
+        configStack->addChild(target);
 }
 
 Setting *TriggeredConfigurationGroup::byName(const QString &settingName)
diff --git a/mythtv/libs/libmyth/mythwidgets.cpp b/mythtv/libs/libmyth/mythwidgets.cpp
index df87fa5..bbd41e9 100644
--- a/mythtv/libs/libmyth/mythwidgets.cpp
+++ b/mythtv/libs/libmyth/mythwidgets.cpp
@@ -223,7 +223,16 @@ void MythCheckBox::keyPressEvent(QKeyEvent* e)
         else if (action == "DOWN")
             focusNextPrevChild(true);
         else if (action == "LEFT" || action == "RIGHT" || action == "SELECT")
-            toggle();
+        {
+            if (isTristate())
+            {
+                Qt::CheckState newState =
+                    (Qt::CheckState)(((int)checkState() + 1) % 3);
+                setCheckState(newState);
+            }
+            else
+                toggle();
+        }
         else
             handled = false;
     }
diff --git a/mythtv/libs/libmyth/mythwidgets.h b/mythtv/libs/libmyth/mythwidgets.h
index 91f2fa7..8cb4dd0 100644
--- a/mythtv/libs/libmyth/mythwidgets.h
+++ b/mythtv/libs/libmyth/mythwidgets.h
@@ -329,11 +329,19 @@ class MPUBLIC MythCheckBox: public QCheckBox
     Q_OBJECT
 
   public:
-    MythCheckBox(QWidget *parent = 0, const char *name = "MythCheckBox")
-        : QCheckBox(parent)       { setObjectName(name); };
+    MythCheckBox(QWidget *parent = 0, const char *name = "MythCheckBox",
+                 bool isTristate = false) : QCheckBox(parent)
+    {
+        setObjectName(name);
+        setTristate(isTristate);
+    }
     MythCheckBox(const QString &text,
-                 QWidget *parent = 0, const char *name = "MythCheckBox")
-        : QCheckBox(text, parent) { setObjectName(name); };
+                 QWidget *parent = 0, const char *name = "MythCheckBox",
+                 bool isTristate = false) : QCheckBox(text, parent)
+    {
+        setObjectName(name);
+        setTristate(isTristate);
+    }
 
     void setHelpText(const QString&);
 
diff --git a/mythtv/libs/libmyth/settings.cpp b/mythtv/libs/libmyth/settings.cpp
index aa79763..bca42b2 100644
--- a/mythtv/libs/libmyth/settings.cpp
+++ b/mythtv/libs/libmyth/settings.cpp
@@ -235,6 +235,20 @@ int SelectSetting::getValueIndex(QString value)
     return -1;
 }
 
+QString SelectSetting::GetValueLabel(const QString &value)
+{
+    selectionList::const_iterator iterValues = values.begin();
+    selectionList::const_iterator iterLabels = labels.begin();
+    for (; iterValues != values.end() && iterLabels != labels.end();
+         ++iterValues, ++iterLabels)
+    {
+        if (*iterValues == value)
+            return *iterLabels;
+    }
+
+    return "???";
+}
+
 bool SelectSetting::ReplaceLabel(const QString &new_label, const QString &value)
 {
     int i = getValueIndex(value);
@@ -299,6 +313,7 @@ QWidget* LineEditSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -327,6 +342,8 @@ QWidget* LineEditSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
 
     widget->setLayout(layout);
 
+    setValue(getValue());
+
     return widget;
 }
 
@@ -336,6 +353,7 @@ void LineEditSetting::widgetInvalid(QObject *obj)
     {
         bxwidget = NULL;
         edit     = NULL;
+        labelWidget = NULL;
     }
 }
 
@@ -373,6 +391,26 @@ void LineEditSetting::setHelpText(const QString &str)
     Setting::setHelpText(str);
 }
 
+static void adjustFont(QWidget *widget, bool isDefault)
+{
+    if (widget)
+    {
+        QFont f = widget->font();
+        f.setWeight(isDefault ? QFont::Light : QFont::Bold);
+        widget->setFont(f);
+    }
+}
+
+void LineEditSetting::setValue(const QString &newValue)
+{
+    if (adjustOnBlank)
+    {
+        adjustFont(labelWidget, newValue.isEmpty());
+        adjustFont(edit,        newValue.isEmpty());
+    }
+    Setting::setValue(newValue);
+}
+
 void BoundedIntegerSetting::setValue(int newValue)
 {
     newValue = std::max(std::min(newValue, max), min);
@@ -439,10 +477,12 @@ QWidget* SliderSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
 
 SpinBoxSetting::SpinBoxSetting(
     Storage *_storage, int _min, int _max, int _step, 
-    bool _allow_single_step, QString _special_value_text) :
+    bool _allow_single_step, QString _special_value_text,
+    bool change_style_on_special) :
     BoundedIntegerSetting(_storage, _min, _max, _step),
     spinbox(NULL), relayEnabled(true),
-    sstep(_allow_single_step), svtext("")
+    sstep(_allow_single_step), svtext(""), labelWidget(NULL),
+    changeOnSpecial(change_style_on_special)
 {
     if (!_special_value_text.isEmpty())
         svtext = _special_value_text;
@@ -476,6 +516,7 @@ QWidget* SpinBoxSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -506,6 +547,8 @@ QWidget* SpinBoxSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
 
     widget->setLayout(layout);
 
+    setValue(intValue());
+
     return widget;
 }
 
@@ -515,12 +558,18 @@ void SpinBoxSetting::widgetInvalid(QObject *obj)
     {
         bxwidget = NULL;
         spinbox  = NULL;
+        labelWidget = NULL;
     }
 }
 
 void SpinBoxSetting::setValue(int newValue)
 {
     newValue = std::max(std::min(newValue, max), min);
+    if (changeOnSpecial)
+    {
+        adjustFont(labelWidget, (newValue == min));
+        adjustFont(spinbox,     (newValue == min));
+    }
     if (spinbox && (spinbox->value() != newValue))
     {
         //int old = intValue();
@@ -631,6 +680,7 @@ QWidget* ComboBoxSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -659,8 +709,12 @@ QWidget* ComboBoxSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
             cbwidget, SLOT(clear()));
 
     if (rw)
+    {
         connect(cbwidget, SIGNAL(editTextChanged(const QString &)),
                 this, SLOT(editTextChanged(const QString &)));
+        connect(cbwidget, SIGNAL(editTextChanged(const QString &)),
+                this, SLOT(changeLabel(const QString &)));
+    }
 
     if (cg)
         connect(cbwidget, SIGNAL(changeHelpText(QString)), cg,
@@ -673,6 +727,8 @@ QWidget* ComboBoxSetting::configWidget(ConfigurationGroup *cg, QWidget* parent,
 
     widget->setLayout(layout);
 
+    setValue(current);
+
     return widget;
 }
 
@@ -682,6 +738,7 @@ void ComboBoxSetting::widgetInvalid(QObject *obj)
     {
         bxwidget = NULL;
         cbwidget = NULL;
+        labelWidget = NULL;
     }
 }
 
@@ -717,6 +774,7 @@ void ComboBoxSetting::setValue(QString newValue)
 
     if (rw)
     {
+        changeLabel(newValue);
         Setting::setValue(newValue);
         if (cbwidget)
             cbwidget->setCurrentIndex(current);
@@ -727,11 +785,21 @@ void ComboBoxSetting::setValue(int which)
 {
     if (cbwidget)
         cbwidget->setCurrentIndex(which);
+    changeLabel(labels[which]);
     SelectSetting::setValue(which);
 }
 
-void ComboBoxSetting::addSelection(
-    const QString &label, QString value, bool select)
+void ComboBoxSetting::changeLabel(const QString &newLabel)
+{
+    if (changeOnSpecial)
+    {
+        adjustFont(labelWidget, specialLabel == newLabel);
+        adjustFont(cbwidget,    specialLabel == newLabel);
+    }
+}
+
+void ComboBoxSetting::addSelection(const QString &label, QString value,
+                                   bool select, bool special_formatting)
 {
     if ((findSelection(label, value) < 0) && cbwidget)
     {
@@ -739,6 +807,12 @@ void ComboBoxSetting::addSelection(
         cbwidget->insertItem(label);
     }
 
+    if (special_formatting)
+    {
+        changeOnSpecial = true;
+        specialLabel = label;
+    }
+
     SelectSetting::addSelection(label, value, select);
 
     if (cbwidget && isSet)
@@ -955,6 +1029,69 @@ void CheckBoxSetting::setHelpText(const QString &str)
     BooleanSetting::setHelpText(str);
 }
 
+QWidget* TristateCheckBoxSetting::configWidget(ConfigurationGroup *cg,
+                                               QWidget* parent,
+                                               const char* widgetName) {
+    widget = new MythCheckBox(parent, widgetName, true);
+    connect(widget, SIGNAL(destroyed(QObject*)),
+            this,   SLOT(widgetDeleted(QObject*)));
+
+    widget->setHelpText(getHelpText());
+    widget->setText(getLabel());
+    widget->setCheckState(tristateValue());
+    setValue(tristateValue());
+
+    connect(widget, SIGNAL(stateChanged(int)),
+            this, SLOT(setValue(int)));
+    connect(this, SIGNAL(valueChanged(int)),
+            this, SLOT(relayValueChanged(int)));
+
+    if (cg)
+        connect(widget, SIGNAL(changeHelpText(QString)), cg,
+                SIGNAL(changeHelpText(QString)));
+
+    return widget;
+}
+
+void TristateCheckBoxSetting::widgetInvalid(QObject *obj)
+{
+    widget = (widget == obj) ? NULL : widget;
+}
+
+void TristateCheckBoxSetting::setEnabled(bool fEnabled)
+{
+    TristateSetting::setEnabled(fEnabled);
+    if (widget)
+        widget->setEnabled(fEnabled);
+}
+
+void TristateCheckBoxSetting::setHelpText(const QString &str)
+{
+    if (widget)
+        widget->setHelpText(str);
+    TristateSetting::setHelpText(str);
+}
+
+const char *TristateSetting::kPartiallyCheckedString = "default";
+
+void TristateCheckBoxSetting::setValue(int check)
+{
+    adjustFont(widget, (check != Qt::Checked && check != Qt::Unchecked));
+    TristateSetting::setValue(check);
+    emit valueChanged(check);
+}
+
+void TristateSetting::setValue(int check)
+{
+    if (check == Qt::Checked)
+        Setting::setValue("1");
+    else if (check == Qt::Unchecked)
+        Setting::setValue("0");
+    else
+        Setting::setValue(kPartiallyCheckedString);
+    emit valueChanged(check);
+}
+
 void AutoIncrementDBSetting::Save(QString table)
 {
     if (intValue() == 0) 
@@ -1142,6 +1279,24 @@ void ImageSelectSetting::addImageSelection(const QString& label,
     addSelection(label, value, select);
 }
 
+void ImageSelectSetting::addDefaultSelection(const QString label,
+                                             const QString value,
+                                             const QString defaultValue,
+                                             bool select)
+{
+    for (unsigned i=0; i<values.size(); i++)
+    {
+        if (values[i] == defaultValue)
+        {
+            changeOnSpecial = true;
+            specialLabel = label;
+            images.push_back(new QImage(*images[i]));
+            addSelection(label, value, select);
+            return;
+        }
+    }
+}
+
 ImageSelectSetting::~ImageSelectSetting()
 {
     Teardown();
@@ -1164,6 +1319,7 @@ void ImageSelectSetting::Teardown(void)
     bxwidget   = NULL;
     imagelabel = NULL;
     combo      = NULL;
+    labelWidget = NULL;
 }
 
 void ImageSelectSetting::imageSet(int num)
@@ -1211,6 +1367,7 @@ QWidget* ImageSelectSetting::configWidget(ConfigurationGroup *cg,
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     combo = new MythComboBox(false);
@@ -1257,6 +1414,10 @@ QWidget* ImageSelectSetting::configWidget(ConfigurationGroup *cg,
     connect(combo, SIGNAL(highlighted(int)), this, SLOT(imageSet(int)));
     connect(combo, SIGNAL(activated(int)), this, SLOT(setValue(int)));
     connect(combo, SIGNAL(activated(int)), this, SLOT(imageSet(int)));
+    connect(combo, SIGNAL(highlighted(const QString &)),
+            this, SLOT(changeLabel(const QString &)));
+    connect(combo, SIGNAL(activated(const QString &)),
+            this, SLOT(changeLabel(const QString &)));
 
     connect(this, SIGNAL(selectionsCleared()),
             combo, SLOT(clear()));
@@ -1267,9 +1428,20 @@ QWidget* ImageSelectSetting::configWidget(ConfigurationGroup *cg,
 
     bxwidget->setLayout(layout);
 
+    changeLabel(GetLabel(current));
+
     return bxwidget;
 }
 
+void ImageSelectSetting::changeLabel(const QString &newLabel)
+{
+    if (changeOnSpecial)
+    {
+        adjustFont(labelWidget, specialLabel == newLabel);
+        adjustFont(combo,       specialLabel == newLabel);
+    }
+}
+
 void ImageSelectSetting::widgetInvalid(QObject *obj)
 {
     if (bxwidget == obj)
diff --git a/mythtv/libs/libmyth/settings.h b/mythtv/libs/libmyth/settings.h
index 10c9939..47fdcec 100644
--- a/mythtv/libs/libmyth/settings.h
+++ b/mythtv/libs/libmyth/settings.h
@@ -134,10 +134,14 @@ class MPUBLIC LabelSetting : public Setting
 
 class MPUBLIC LineEditSetting : public Setting
 {
+    Q_OBJECT
+
   protected:
-    LineEditSetting(Storage *_storage, bool readwrite = true) :
+    LineEditSetting(Storage *_storage, bool readwrite = true,
+                    bool adjust_on_blank = false) :
         Setting(_storage), bxwidget(NULL), edit(NULL),
-        rw(readwrite), password_echo(false) { }
+        rw(readwrite), password_echo(false),
+        adjustOnBlank(adjust_on_blank), labelWidget(NULL) { }
 
   public:
     virtual QWidget* configWidget(ConfigurationGroup *cg, QWidget* parent, 
@@ -159,11 +163,16 @@ class MPUBLIC LineEditSetting : public Setting
 
     virtual void setHelpText(const QString &str);
 
+  public slots:
+    virtual void setValue(const QString &newValue);
+
   private:
     QWidget      *bxwidget;
     MythLineEdit *edit;
     bool rw;
     bool password_echo;
+    bool adjustOnBlank;
+    QWidget *labelWidget;
 };
 
 // TODO: set things up so that setting the value as a string emits
@@ -219,7 +228,8 @@ class MPUBLIC SpinBoxSetting: public BoundedIntegerSetting
   public:
     SpinBoxSetting(Storage *_storage, int min, int max, int step, 
                    bool allow_single_step = false,
-                   QString special_value_text = "");
+                   QString special_value_text = "",
+                   bool change_style_on_special = false);
 
     virtual QWidget *configWidget(ConfigurationGroup *cg, QWidget *parent, 
                                   const char *widgetName = 0);
@@ -248,6 +258,8 @@ class MPUBLIC SpinBoxSetting: public BoundedIntegerSetting
     bool         relayEnabled;
     bool         sstep;
     QString      svtext;
+    QLabel      *labelWidget;
+    bool         changeOnSpecial;
 };
 
 class MPUBLIC SelectSetting : public Setting
@@ -277,6 +289,7 @@ class MPUBLIC SelectSetting : public Setting
         { return (i < labels.size()) ? labels[i] : QString::null; }
     virtual QString GetValue(uint i) const
         { return (i < values.size()) ? values[i] : QString::null; }
+    virtual QString GetValueLabel(const QString &value);
 
 signals:
     void selectionAdded(const QString& label, QString value);
@@ -318,7 +331,8 @@ class MPUBLIC ComboBoxSetting: public SelectSetting {
 protected:
     ComboBoxSetting(Storage *_storage, bool _rw = false, int _step = 1) :
         SelectSetting(_storage), rw(_rw),
-        bxwidget(NULL), cbwidget(NULL), step(_step) { }
+        bxwidget(NULL), cbwidget(NULL), changeOnSpecial(false),
+        specialLabel(""), labelWidget(NULL), step(_step) { }
 
 public:
     virtual void setValue(QString newValue);
@@ -340,15 +354,20 @@ public:
 public slots:
     void addSelection(const QString &label,
                       QString value = QString::null,
-                      bool select = false);
+                      bool select = false,
+                      bool special_formatting = false);
     bool removeSelection(const QString &label,
                          QString value = QString::null);
+    virtual void changeLabel(const QString &newValue);
     void editTextChanged(const QString &newText);
 
 private:
     bool rw;
     QWidget      *bxwidget;
     MythComboBox *cbwidget;
+    bool          changeOnSpecial;
+    QString       specialLabel;
+    QLabel       *labelWidget;
 
 protected:
     int step;
@@ -417,7 +436,8 @@ public:
     ImageSelectSetting(Storage *_storage) :
         SelectSetting(_storage),
         bxwidget(NULL), imagelabel(NULL), combo(NULL),
-        m_hmult(1.0f), m_wmult(1.0f) { }
+        m_hmult(1.0f), m_wmult(1.0f),
+        changeOnSpecial(false), specialLabel(""), labelWidget(NULL) { }
     virtual QWidget* configWidget(ConfigurationGroup *cg, QWidget* parent, 
                                   const char* widgetName = 0);
     virtual void widgetInvalid(QObject *obj);
@@ -428,9 +448,14 @@ public:
                                    QImage* image,
                                    QString value=QString::null,
                                    bool select=false);
+    virtual void addDefaultSelection(const QString label,
+                                     const QString value,
+                                     const QString defaultValue,
+                                     bool select);
 
 protected slots:
     void imageSet(int);
+    void changeLabel(const QString &newLabel);
 
   protected:
     void Teardown(void);
@@ -442,6 +467,9 @@ protected:
     QLabel *imagelabel;
     MythComboBox *combo;
     float m_hmult, m_wmult;
+    bool          changeOnSpecial;
+    QString       specialLabel;
+    QLabel       *labelWidget;
 };
 
 class MPUBLIC BooleanSetting : public Setting
@@ -484,6 +512,56 @@ protected:
     MythCheckBox *widget;
 };
 
+class MPUBLIC TristateSetting : public BooleanSetting
+{
+    Q_OBJECT
+
+  public:
+    TristateSetting(Storage *_storage) : BooleanSetting(_storage) {}
+
+    Qt::CheckState tristateValue(void) const {
+        if (getValue() == "0")
+            return Qt::Unchecked;
+        if (getValue() == "1")
+            return Qt::Checked;
+        return Qt::PartiallyChecked;
+    }
+
+    static const char *kPartiallyCheckedString;
+
+public slots:
+    virtual void setValue(/*Qt::CheckState*/int check);
+
+signals:
+    void valueChanged(int);
+};
+
+class MPUBLIC TristateCheckBoxSetting: public TristateSetting {
+    Q_OBJECT
+
+public:
+    TristateCheckBoxSetting(Storage *_storage) :
+        TristateSetting(_storage), widget(NULL) { }
+    virtual QWidget* configWidget(ConfigurationGroup *cg, QWidget* parent,
+                                  const char* widgetName = 0);
+    virtual void widgetInvalid(QObject*);
+
+    virtual void setEnabled(bool b);
+
+    virtual void setHelpText(const QString &str);
+
+
+public slots:
+    virtual void setValue(/*Qt::CheckState*/int check);
+    virtual void relayValueChanged(int state) {
+        if (widget)
+            widget->setCheckState((Qt::CheckState)state);
+    }
+
+protected:
+    MythCheckBox *widget;
+};
+
 class MPUBLIC PathSetting : public ComboBoxSetting
 {
 public:
diff --git a/mythtv/libs/libmythtv/DetectLetterbox.cpp b/mythtv/libs/libmythtv/DetectLetterbox.cpp
index 9fe7516..625045e 100644
--- a/mythtv/libs/libmythtv/DetectLetterbox.cpp
+++ b/mythtv/libs/libmythtv/DetectLetterbox.cpp
@@ -5,10 +5,11 @@
 #include "mythplayer.h"
 #include "videoouttypes.h"
 #include "mythcorecontext.h"
+#include "playsettings.h"
 
 DetectLetterbox::DetectLetterbox(MythPlayer* const player)
 {
-    int dbAdjustFill = gCoreContext->GetNumSetting("AdjustFill", 0);
+    int dbAdjustFill = player->GetPlaySettings()->GetNumSetting("AdjustFill", 0);
     isDetectLetterbox = dbAdjustFill >= kAdjustFill_AutoDetect_DefaultOff;
     firstFrameChecked = 0;
     detectLetterboxDefaultMode = (AdjustFillMode) max((int) kAdjustFill_Off,
@@ -18,7 +19,8 @@ DetectLetterbox::DetectLetterbox(MythPlayer* const player)
     detectLetterboxPossibleFullFrame = -1;
     detectLetterboxConsecutiveCounter = 0;
     detectLetterboxDetectedMode = player->GetAdjustFill();
-    detectLetterboxLimit = gCoreContext->GetNumSetting("DetectLeterboxLimit", 75);
+    detectLetterboxLimit =
+        player->GetPlaySettings()->GetNumSetting("DetectLeterboxLimit", 75);
     m_player = player;
 }
 
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 3bceff4..991304e 100644
--- a/mythtv/libs/libmythtv/avformatdecoder.cpp
+++ b/mythtv/libs/libmythtv/avformatdecoder.cpp
@@ -37,6 +37,7 @@ using namespace std;
 #include "bdringbuffer.h"
 #include "videodisplayprofile.h"
 #include "mythuihelper.h"
+#include "playsettings.h"
 
 #include "lcddevice.h"
 
@@ -317,7 +318,7 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
 
     cc608_build_parity_table(cc608_parity_table);
 
-    if (gCoreContext->GetNumSetting("CCBackground", 0))
+    if (GetPlayer()->GetPlaySettings()->GetNumSetting("CCBackground", 0))
         CC708Window::forceWhiteOnBlackText = true;
 
     no_dts_hack = false;
@@ -1260,7 +1261,7 @@ void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,
     if (selectedStream)
     {
         directrendering = true;
-        if (!gCoreContext->GetNumSetting("DecodeExtraAudio", 0) &&
+        if (!GetPlayer()->GetPlaySettings()->GetNumSetting("DecodeExtraAudio", 0) &&
             !CODEC_IS_HWACCEL(codec, enc))
         {
             SetLowBuffers(false);
@@ -1786,7 +1787,7 @@ int AvFormatDecoder::ScanStreams(bool novideo)
 
                 if (!is_db_ignored)
                 {
-                    VideoDisplayProfile vdp;
+                    VideoDisplayProfile vdp(GetPlayer()->GetPlaySettings());
                     vdp.SetInput(QSize(width, height));
                     dec = vdp.GetDecoder();
                     thread_count = vdp.GetMaxCPUs();
@@ -1814,7 +1815,8 @@ int AvFormatDecoder::ScanStreams(bool novideo)
                     MythCodecID vdpau_mcid;
                     vdpau_mcid = VideoOutputVDPAU::GetBestSupportedCodec(
                         width, height,
-                        mpeg_version(enc->codec_id), no_hardware_decoders);
+                        mpeg_version(enc->codec_id), no_hardware_decoders,
+                        GetPlayer()->GetPlaySettings());
 
                     if (vdpau_mcid >= video_codec_id)
                     {
diff --git a/mythtv/libs/libmythtv/dbcheck.cpp b/mythtv/libs/libmythtv/dbcheck.cpp
index daf4123..5b4424f 100644
--- a/mythtv/libs/libmythtv/dbcheck.cpp
+++ b/mythtv/libs/libmythtv/dbcheck.cpp
@@ -3564,7 +3564,8 @@ NULL
 
             VideoDisplayProfile::CreateNewProfiles(host);
             profiles = VideoDisplayProfile::GetProfiles(host);
-            QString profile = VideoDisplayProfile::GetDefaultProfileName(host);
+            QString profile =
+                VideoDisplayProfile::GetDefaultProfileName(host, NULL);
 
             if (profiles.contains("Normal") &&
                 (profile=="CPU++" || profile=="CPU+" || profile=="CPU--"))
@@ -6216,6 +6217,13 @@ tmp.constData(),
 "  jump int(11) NOT NULL default '0',"
 "  PRIMARY KEY  (`name`)"
 ");",
+"CREATE TABLE playgroupsettings ("
+"  playgroupname varchar(64) NOT NULL,"
+"  `value` varchar(128) NOT NULL,"
+"  `data` text,"
+"  overridden tinyint(1) NOT NULL,"
+"  PRIMARY KEY (playgroupname, `value`)"
+");",
 "CREATE TABLE powerpriority ("
 "  priorityname varchar(64) collate utf8_bin NOT NULL,"
 "  recpriority int(10) NOT NULL default '0',"
diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index c374956..08bd08b 100644
--- a/mythtv/libs/libmythtv/mythplayer.cpp
+++ b/mythtv/libs/libmythtv/mythplayer.cpp
@@ -60,6 +60,7 @@ using namespace std;
 #include "mythimage.h"
 #include "mythuiimage.h"
 #include "mythlogging.h"
+#include "playsettings.h"
 
 extern "C" {
 #include "vbitext/vbi.h"
@@ -215,21 +216,9 @@ MythPlayer::MythPlayer(bool muted)
     memset(&tc_wrap,    0, sizeof(tc_wrap));
 
     playerThread = QThread::currentThread();
-    // Playback (output) zoom control
-    detect_letter_box = new DetectLetterbox(this);
-
-    vbimode = VBIMode::Parse(gCoreContext->GetSetting("VbiFormat"));
-
     defaultDisplayAspect =
         gCoreContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
                                             gCoreContext->GetHostName(), 1.3333);
-    captionsEnabledbyDefault = gCoreContext->GetNumSetting("DefaultCCMode");
-    decode_extra_audio = gCoreContext->GetNumSetting("DecodeExtraAudio", 0);
-    itvEnabled         = gCoreContext->GetNumSetting("EnableMHEG", 0);
-    db_prefer708       = gCoreContext->GetNumSetting("Prefer708Captions", 1);
-    clearSavedPosition = gCoreContext->GetNumSetting("ClearSavedPosition", 1);
-    endExitPrompt      = gCoreContext->GetNumSetting("EndOfRecordingExitPrompt");
-    pip_default_loc    = (PIPLocation)gCoreContext->GetNumSetting("PIPLocation", kPIPTopLeft);
     tc_wrap[TC_AUDIO]  = gCoreContext->GetNumSetting("AudioSyncOffset", 0);
 
     // Get VBI page number
@@ -457,7 +446,7 @@ bool MythPlayer::InitVideo(void)
     if (using_null_videoout && decoder)
     {
         MythCodecID codec = decoder->GetVideoCodecID();
-        videoOutput = new VideoOutputNull();
+        videoOutput = new VideoOutputNull(GetPlaySettings());
         if (!videoOutput->Init(video_disp_dim.width(), video_disp_dim.height(),
                                video_aspect, 0, QRect(), codec))
         {
@@ -506,7 +495,7 @@ bool MythPlayer::InitVideo(void)
                 decoder->GetVideoCodecPrivate(),
                 pipState,
                 video_disp_dim, video_aspect,
-                widget->winId(), display_rect, video_frame_rate);
+                widget->winId(), display_rect, video_frame_rate, GetPlaySettings());
         }
 
         if (videoOutput)
@@ -593,7 +582,7 @@ void MythPlayer::ReinitOSD(void)
 
 void MythPlayer::ReinitVideo(void)
 {
-    if (!videoOutput->IsPreferredRenderer(video_disp_dim))
+    if (!videoOutput->IsPreferredRenderer(video_disp_dim, GetPlaySettings()))
     {
         LOG(VB_PLAYBACK, LOG_INFO, LOC + "Need to switch video renderer.");
         SetErrored(QObject::tr("Need to switch video renderer."));
@@ -2160,7 +2149,8 @@ void MythPlayer::VideoStart(void)
         m_double_process = videoOutput->IsExtraProcessingRequired();
 
         videosync = VideoSync::BestMethod(
-            videoOutput, (uint)fr_int, (uint)rf_int, m_double_framerate);
+            videoOutput, GetPlaySettings(),
+            (uint)fr_int, (uint)rf_int, m_double_framerate);
 
         // Make sure video sync can do it
         if (videosync != NULL && m_double_framerate)
@@ -3562,5 +3552,18 @@ void MythPlayer::SetPlayerInfo(TV *tv, QWidget *widget,
     player_ctx   = ctx;
     livetv       = ctx->tvchain;
+
+    vbimode = VBIMode::Parse(GetPlaySettings()->GetSetting("VbiFormat", ""));
+
+    // Playback (output) zoom control
+    detect_letter_box = new DetectLetterbox(this);
+
+    captionsEnabledbyDefault = GetPlaySettings()->GetNumSetting("DefaultCCMode", 0);
+    decode_extra_audio = GetPlaySettings()->GetNumSetting("DecodeExtraAudio", 0);
+    itvEnabled = GetPlaySettings()->GetNumSetting("EnableMHEG", 0);
+    db_prefer708 = GetPlaySettings()->GetNumSetting("Prefer708Captions", 1);
+    clearSavedPosition = GetPlaySettings()->GetNumSetting("ClearSavedPosition", 1);
+    endExitPrompt      = GetPlaySettings()->GetNumSetting("EndOfRecordingExitPrompt", 0);
+    pip_default_loc    = (PIPLocation)GetPlaySettings()->GetNumSetting("PIPLocation", kPIPTopLeft);
 }
 
 bool MythPlayer::EnableEdit(void)
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index b8b7244..166bac4 100644
--- a/mythtv/libs/libmythtv/mythplayer.h
+++ b/mythtv/libs/libmythtv/mythplayer.h
@@ -177,6 +177,10 @@ class MTV_PUBLIC MythPlayer
     QString   GetXDS(const QString &key) const;
     PIPLocation GetNextPIPLocation(void) const;
 
+    PlaySettings *GetPlaySettings(void) const {
+        return player_ctx ? player_ctx->settings : NULL;
+    }
+
     // Bool Gets
     bool    IsPaused(void)                    { return allpaused;      }
     bool    GetRawAudioState(void) const;
diff --git a/mythtv/libs/libmythtv/playercontext.cpp b/mythtv/libs/libmythtv/playercontext.cpp
index 4acc16a..bff747b 100644
--- a/mythtv/libs/libmythtv/playercontext.cpp
+++ b/mythtv/libs/libmythtv/playercontext.cpp
@@ -17,6 +17,8 @@
 #include "mythcorecontext.h"
 #include "videometadatautil.h"
 #include "mythlogging.h"
+#include "DetectLetterbox.h"
+#include "playsettings.h"
 
 #define LOC QString("playCtx: ")
 #define LOC_ERR QString("playCtx, Error: ")
@@ -375,7 +377,7 @@ bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
                                  bool embed, const QRect &embedbounds,
                                  bool muted)
 {
-    int exact_seeking = gCoreContext->GetNumSetting("ExactSeeking", 0);
+    int exact_seeking = settings->GetNumSetting("ExactSeeking", 0);
 
     if (HasPlayer())
     {
@@ -418,7 +420,7 @@ bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
     {
         QString subfn = buffer->GetSubtitleFilename();
         if (!subfn.isEmpty() && player->GetSubReader())
-            player->GetSubReader()->LoadExternalSubtitles(subfn);
+            player->GetSubReader()->LoadExternalSubtitles(subfn, settings);
     }
 
     if (embed && !embedbounds.isNull())
@@ -839,7 +841,8 @@ void PlayerContext::SetRingBuffer(RingBuffer *buf)
 /**
  * \brief assign programinfo to the context
  */
-void PlayerContext::SetPlayingInfo(const ProgramInfo *info)
+void PlayerContext::SetPlayingInfo(const ProgramInfo *info,
+                                   PlaySettings *_settings)
 {
     bool ignoreDB = gCoreContext->IsDatabaseIgnored();
 
@@ -851,6 +854,7 @@ void PlayerContext::SetPlayingInfo(const ProgramInfo *info)
             playingInfo->MarkAsInUse(false, recUsage);
         delete playingInfo;
         playingInfo = NULL;
+        // XXX delete settings?
     }
 
     if (info)
@@ -859,6 +863,8 @@ void PlayerContext::SetPlayingInfo(const ProgramInfo *info)
         if (!ignoreDB)
             playingInfo->MarkAsInUse(true, recUsage);
         playingLen = playingInfo->GetSecondsInRecording();
+        settings = (_settings ? _settings :
+                    new PlaySettings(playingInfo->GetPlaybackGroup()));
     }
 }
 
diff --git a/mythtv/libs/libmythtv/playercontext.h b/mythtv/libs/libmythtv/playercontext.h
index 6a6a767..fd2a0e7 100644
--- a/mythtv/libs/libmythtv/playercontext.h
+++ b/mythtv/libs/libmythtv/playercontext.h
@@ -25,6 +25,7 @@ class ProgramInfo;
 class LiveTVChain;
 class MythDialog;
 class QPainter;
+class PlaySettings;
 
 struct osdInfo
 {
@@ -96,7 +97,7 @@ class MTV_PUBLIC PlayerContext
     void SetRecorder(RemoteEncoder *rec);
     void SetTVChain(LiveTVChain *chain);
     void SetRingBuffer(RingBuffer *buf);
-    void SetPlayingInfo(const ProgramInfo *info);
+    void SetPlayingInfo(const ProgramInfo *info, PlaySettings *settings=NULL);
     void SetPlayGroup(const QString &group);
     void SetPseudoLiveTV(const ProgramInfo *pi, PseudoState new_state);
     void SetPIPLocation(int loc) { pipLocation = loc; }
@@ -153,6 +154,7 @@ class MTV_PUBLIC PlayerContext
     LiveTVChain        *tvchain;
     RingBuffer         *buffer;
     ProgramInfo        *playingInfo; ///< Currently playing info
+    PlaySettings       *settings; // corresponding to playingInfo
     long long           playingLen;  ///< Initial CalculateLength()
     AVSpecialDecode     specialDecode;
     bool                nohardwaredecoders; // < Disable use of VDPAU decoding
diff --git a/mythtv/libs/libmythtv/playgroup.cpp b/mythtv/libs/libmythtv/playgroup.cpp
index 1480874..4817f67 100644
--- a/mythtv/libs/libmythtv/playgroup.cpp
+++ b/mythtv/libs/libmythtv/playgroup.cpp
@@ -2,6 +2,7 @@
 #include "playgroup.h"
 #include "programinfo.h"
 #include "mythwidgets.h"
+#include "playsettings.h"
 
 class PlayGroupConfig: public ConfigurationWizard
 {
@@ -220,8 +221,9 @@ int PlayGroup::GetSetting(const QString &name, const QString &field,
     return res;
 }
 
-PlayGroupEditor::PlayGroupEditor(void) :
-    listbox(new ListBoxSetting(this)), lastValue("Default")
+PlayGroupEditor::PlayGroupEditor(SettingsLookup *funcArray, int funcArraySize) :
+    listbox(new ListBoxSetting(this)), lastValue("Default"),
+    getSettings(funcArray), getSettingsSize(funcArraySize)
 {
     listbox->setLabel(tr("Playback Groups"));
     addChild(listbox);
@@ -252,6 +254,9 @@ void PlayGroupEditor::open(QString name)
     }
 
     PlayGroupConfig group(name);
+    PlaySettings *psettings = new PlaySettings(name);
+    for (int i=0; i<getSettingsSize; i++)
+        getSettings[i](psettings, &group);
     if (group.exec() == QDialog::Accepted || !created)
         lastValue = name;
     else
@@ -286,6 +291,7 @@ void PlayGroupEditor::doDelete(void)
         query.bindValue(":NAME", name);
         if (!query.exec())
             MythDB::DBError("PlayGroupEditor::doDelete", query);
+        PlaySettings::deleteGroup(name);
 
         int lastIndex = listbox->getValueIndex(name);
         lastValue = "";
diff --git a/mythtv/libs/libmythtv/playgroup.h b/mythtv/libs/libmythtv/playgroup.h
index 0eed2ae..785a730 100644
--- a/mythtv/libs/libmythtv/playgroup.h
+++ b/mythtv/libs/libmythtv/playgroup.h
@@ -7,6 +7,7 @@
 #include "settings.h"
 
 class ProgramInfo;
+class PlaySettings;
 
 class MTV_PUBLIC PlayGroup
 {
@@ -23,7 +24,9 @@ class MTV_PUBLIC PlayGroupEditor : public QObject, public ConfigurationDialog
     Q_OBJECT
 
   public:
-    PlayGroupEditor(void);
+    typedef ConfigurationWizard *(*SettingsLookup)(PlaySettings *settings,
+                                                   ConfigurationWizard *base);
+    PlayGroupEditor(SettingsLookup *funcArray, int funcArraySize);
     virtual DialogCode exec(void);
     virtual void Load(void);
     virtual void Save(void) { }
@@ -38,6 +41,8 @@ class MTV_PUBLIC PlayGroupEditor : public QObject, public ConfigurationDialog
   protected:
     ListBoxSetting *listbox;
     QString         lastValue;
+    SettingsLookup *getSettings;
+    int             getSettingsSize;
 };
 
 #endif
diff --git a/mythtv/libs/libmythtv/subtitlereader.cpp b/mythtv/libs/libmythtv/subtitlereader.cpp
index a6eb2e4..736f341 100644
--- a/mythtv/libs/libmythtv/subtitlereader.cpp
+++ b/mythtv/libs/libmythtv/subtitlereader.cpp
@@ -65,10 +65,12 @@ void SubtitleReader::FreeAVSubtitle(const AVSubtitle &subtitle)
         av_free(subtitle.rects);
 }
 
-bool SubtitleReader::LoadExternalSubtitles(const QString &subtitleFileName)
+bool SubtitleReader::LoadExternalSubtitles(const QString &subtitleFileName,
+                                           PlaySettings *settings)
 {
     m_TextSubtitles.Clear();
-    return TextSubtitleParser::LoadSubtitles(subtitleFileName, m_TextSubtitles);
+    return TextSubtitleParser::LoadSubtitles(subtitleFileName, m_TextSubtitles,
+                                             settings);
 }
 
 bool SubtitleReader::HasTextSubtitles(void)
diff --git a/mythtv/libs/libmythtv/subtitlereader.h b/mythtv/libs/libmythtv/subtitlereader.h
index cc6591e..13dbe83 100644
--- a/mythtv/libs/libmythtv/subtitlereader.h
+++ b/mythtv/libs/libmythtv/subtitlereader.h
@@ -44,7 +44,7 @@ class SubtitleReader
 
     TextSubtitles* GetTextSubtitles(void) { return &m_TextSubtitles; }
     bool HasTextSubtitles(void);
-    bool LoadExternalSubtitles(const QString &videoFile);
+    bool LoadExternalSubtitles(const QString &videoFile, PlaySettings *settings);
 
     QStringList GetRawTextSubtitles(uint64_t &duration);
     void AddRawTextSubtitle(QStringList list, uint64_t duration);
diff --git a/mythtv/libs/libmythtv/subtitlescreen.cpp b/mythtv/libs/libmythtv/subtitlescreen.cpp
index 60b90e2..8867532 100644
--- a/mythtv/libs/libmythtv/subtitlescreen.cpp
+++ b/mythtv/libs/libmythtv/subtitlescreen.cpp
@@ -8,6 +8,7 @@
 #include "mythpainter.h"
 #include "subtitlescreen.h"
 #include "bdringbuffer.h"
+#include "playsettings.h"
 
 #define LOC      QString("Subtitles: ")
 #define LOC_WARN QString("Subtitles Warning: ")
@@ -80,8 +81,8 @@ bool SubtitleScreen::Create(void)
         LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to get CEA-608 reader.");
     if (!m_708reader)
         LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to get CEA-708 reader.");
-    m_useBackground = (bool)gCoreContext->GetNumSetting("CCBackground", 0);
-    m_textFontZoom  = gCoreContext->GetNumSetting("OSDCC708TextZoom", 100);
+    m_useBackground = (bool)m_player->GetPlaySettings()->GetNumSetting("CCBackground", 0);
+    m_textFontZoom   = m_player->GetPlaySettings()->GetNumSetting("OSDCC708TextZoom", 100);
     return true;
 }
 
diff --git a/mythtv/libs/libmythtv/textsubtitleparser.cpp b/mythtv/libs/libmythtv/textsubtitleparser.cpp
index b15c4d5..09cb3b1 100644
--- a/mythtv/libs/libmythtv/textsubtitleparser.cpp
+++ b/mythtv/libs/libmythtv/textsubtitleparser.cpp
@@ -21,6 +21,7 @@ using std::lower_bound;
 #include "ringbuffer.h"
 #include "textsubtitleparser.h"
 #include "xine_demux_sputext.h"
+#include "playsettings.h"
 
 static bool operator<(const text_subtitle_t& left,
                       const text_subtitle_t& right)
@@ -116,7 +117,8 @@ void TextSubtitles::Clear(void)
     m_lock.unlock();
 }
 
-bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target)
+bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target,
+                                       PlaySettings *settings)
 {
     demux_sputext_t sub_data;
     sub_data.rbuffer = RingBuffer::Create(fileName, 0, false);
@@ -134,7 +136,7 @@ bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target)
     target.SetFrameBasedTiming(!sub_data.uses_time);
 
     QTextCodec *textCodec = NULL;
-    QString codec = gCoreContext->GetSetting("SubtitleCodec", "");
+    QString codec = settings->GetSetting("SubtitleCodec", "");
     if (!codec.isEmpty())
         textCodec = QTextCodec::codecForName(codec.toLatin1());
     if (!textCodec)
diff --git a/mythtv/libs/libmythtv/textsubtitleparser.h b/mythtv/libs/libmythtv/textsubtitleparser.h
index 8f9a23e..3802ba1 100644
--- a/mythtv/libs/libmythtv/textsubtitleparser.h
+++ b/mythtv/libs/libmythtv/textsubtitleparser.h
@@ -17,6 +17,8 @@ using namespace std;
 // Qt headers
 #include <QStringList>
 
+class PlaySettings;
+
 class text_subtitle_t
 {
   public:
@@ -83,7 +85,8 @@ class TextSubtitles
 class TextSubtitleParser
 {
   public:
-    static bool LoadSubtitles(QString fileName, TextSubtitles &target);
+    static bool LoadSubtitles(QString fileName, TextSubtitles &target,
+                              PlaySettings *settings);
 };
 
 #endif
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
index 83126f1..a4f5c50 100644
--- a/mythtv/libs/libmythtv/tv_play.cpp
+++ b/mythtv/libs/libmythtv/tv_play.cpp
@@ -58,6 +58,7 @@ using namespace std;
 #include "mythdirs.h"
 #include "tvbrowsehelper.h"
 #include "mythlogging.h"
+#include "playsettings.h"
 
 #if ! HAVE_ROUND
 #define round(x) ((int) ((x) + 0.5))
@@ -208,7 +209,6 @@ bool TV::StartTV(ProgramInfo *tvrec, uint flags)
     bool startInGuide = flags & kStartTVInGuide;
     bool inPlaylist = flags & kStartTVInPlayList;
     bool initByNetworkCommand = flags & kStartTVByNetworkCommand;
-    TV *tv = new TV();
     bool quitAll = false;
     bool showDialogs = true;
     bool playCompleted = false;
@@ -222,6 +222,9 @@ bool TV::StartTV(ProgramInfo *tvrec, uint flags)
         curProgram->SetIgnoreBookmark(flags & kStartTVIgnoreBookmark);
     }
 
+    PlaySettings settings(curProgram ? curProgram->GetPlaybackGroup() : "Default");
+    TV *tv = new TV(&settings);
+
     // Initialize TV
     if (!tv->Init())
     {
@@ -252,7 +255,7 @@ bool TV::StartTV(ProgramInfo *tvrec, uint flags)
         if (curProgram)
         {
             LOG(VB_PLAYBACK, LOG_INFO, LOC + "tv->Playback() -- begin");
-            if (!tv->Playback(*curProgram))
+            if (!tv->Playback(*curProgram, &settings))
             {
                 quitAll = true;
             }
@@ -779,7 +782,7 @@ void TV::ResetKeys(void)
 /** \fn TV::TV(void)
  *  \sa Init(void)
  */
-TV::TV(void)
+TV::TV(PlaySettings *settings)
     : // Configuration variables from database
       baseFilters(""),
       db_channel_format("<num> <sign>"),
@@ -877,12 +880,12 @@ TV::TV(void)
     playerActive = 0;
     playerLock.unlock();
 
-    InitFromDB();
+    InitFromDB(settings);
 
     LOG(VB_PLAYBACK, LOG_INFO, LOC + "Finished creating TV object");
 }
 
-void TV::InitFromDB(void)
+void TV::InitFromDB(PlaySettings *settings)
 {
     QMap<QString,QString> kv;
     kv["LiveTVIdleTimeout"]        = "0";
@@ -928,6 +931,7 @@ void TV::InitFromDB(void)
         kv[QString("FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
 
     MythDB::getMythDB()->GetSettings(kv);
+    settings->AddToMap(kv);
 
     QString db_time_format;
     QString db_short_date_format;
@@ -1685,7 +1689,7 @@ void TV::HandleOSDAskAllow(PlayerContext *ctx, QString action)
     askAllowLock.unlock();
 }
 
-int TV::Playback(const ProgramInfo &rcinfo)
+int TV::Playback(const ProgramInfo &rcinfo, PlaySettings *settings)
 {
     wantsToQuit   = false;
     jumpToProgram = false;
@@ -1699,7 +1703,7 @@ int TV::Playback(const ProgramInfo &rcinfo)
         return 0;
     }
 
-    mctx->SetPlayingInfo(&rcinfo);
+    mctx->SetPlayingInfo(&rcinfo, settings);
     mctx->SetInitialTVState(false);
     HandleStateChange(mctx, mctx);
 
@@ -2062,7 +2066,9 @@ void TV::HandleStateChange(PlayerContext *mctx, PlayerContext *ctx)
             QString msg = tr("%1 Settings")
                     .arg(tv_i18n(ctx->playingInfo->GetPlaybackGroup()));
             ctx->UnlockPlayingInfo(__FILE__, __LINE__);
-            if (count > 0)
+            if (count > 0 &&
+                ctx->playingInfo->GetPlaybackGroup() != "Default" &&
+                ctx->playingInfo->GetPlaybackGroup() != "Videos")
                 SetOSDMessage(ctx, msg);
             ITVRestart(ctx, false);
         }
diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
index 1a6264b..4137d97 100644
--- a/mythtv/libs/libmythtv/tv_play.h
+++ b/mythtv/libs/libmythtv/tv_play.h
@@ -59,6 +59,7 @@ class OSDListTreeItemEnteredEvent;
 class OSDListTreeItemSelectedEvent;
 class TVBrowseHelper;
 struct osdInfo;
+class PlaySettings;
 
 typedef QMap<QString,InfoMap>    DDValueMap;
 typedef QMap<QString,DDValueMap> DDKeyMap;
@@ -164,10 +165,10 @@ class MTV_PUBLIC TV : public QObject
         unsigned long seconds;
     };
 
-    TV(void);
+    TV(PlaySettings *settings);
    ~TV();
 
-    void InitFromDB(void);
+    void InitFromDB(PlaySettings *settings);
     bool Init(bool createWindow = true);
 
     // User input processing commands
@@ -192,7 +193,7 @@ class MTV_PUBLIC TV : public QObject
 
     // Recording commands
     int  PlayFromRecorder(int recordernum);
-    int  Playback(const ProgramInfo &rcinfo);
+    int  Playback(const ProgramInfo &rcinfo, PlaySettings *settings);
 
     // Commands used by frontend playback box
     QString GetRecordingGroup(int player_idx) const;
diff --git a/mythtv/libs/libmythtv/videodisplayprofile.cpp b/mythtv/libs/libmythtv/videodisplayprofile.cpp
index bb31bb0..35c6aaa 100644
--- a/mythtv/libs/libmythtv/videodisplayprofile.cpp
+++ b/mythtv/libs/libmythtv/videodisplayprofile.cpp
@@ -8,6 +8,7 @@ using namespace std;
 #include "mythlogging.h"
 #include "videooutbase.h"
 #include "avformatdecoder.h"
+#include "playsettings.h"
 
 bool ProfileItem::IsMatch(const QSize &size, float rate) const
 {
@@ -212,7 +213,7 @@ priority_map_t VideoDisplayProfile::safe_renderer_priority;
 pref_map_t  VideoDisplayProfile::dec_name;
 safe_list_t VideoDisplayProfile::safe_decoders;
 
-VideoDisplayProfile::VideoDisplayProfile()
+VideoDisplayProfile::VideoDisplayProfile(PlaySettings *settings)
     : lock(QMutex::Recursive), last_size(0,0), last_rate(0.0f),
       last_video_renderer(QString::null)
 {
@@ -220,7 +221,7 @@ VideoDisplayProfile::VideoDisplayProfile()
     init_statics();
 
     QString hostname    = gCoreContext->GetHostName();
-    QString cur_profile = GetDefaultProfileName(hostname);
+    QString cur_profile = GetDefaultProfileName(hostname, settings);
     uint    groupid     = GetProfileGroupID(cur_profile, hostname);
 
     item_list_t items = LoadDB(groupid);
@@ -770,9 +771,11 @@ QStringList VideoDisplayProfile::GetProfiles(const QString &hostname)
     return list;
 }
 
-QString VideoDisplayProfile::GetDefaultProfileName(const QString &hostname)
+QString VideoDisplayProfile::GetDefaultProfileName(const QString &hostname,
+                                                   PlaySettings *settings)
 {
     QString tmp =
+        settings ? settings->GetSetting("DefaultVideoPlaybackProfile", "") :
         gCoreContext->GetSettingOnHost("DefaultVideoPlaybackProfile", hostname);
 
     QStringList profiles = GetProfiles(hostname);
diff --git a/mythtv/libs/libmythtv/videodisplayprofile.h b/mythtv/libs/libmythtv/videodisplayprofile.h
index e71978b..b71b5ed 100644
--- a/mythtv/libs/libmythtv/videodisplayprofile.h
+++ b/mythtv/libs/libmythtv/videodisplayprofile.h
@@ -14,6 +14,8 @@ using namespace std;
 #include "mythtvexp.h"
 #include "mythcontext.h"
 
+class PlaySettings;
+
 typedef QMap<QString,QString>     pref_map_t;
 typedef QMap<QString,QStringList> safe_map_t;
 typedef QStringList               safe_list_t;
@@ -81,7 +83,7 @@ typedef vector<ProfileItem>       item_list_t;
 class MTV_PUBLIC VideoDisplayProfile
 {
   public:
-    VideoDisplayProfile();
+    VideoDisplayProfile(PlaySettings *settings);
     ~VideoDisplayProfile();
 
     void SetInput(const QSize &size);
@@ -126,7 +128,8 @@ class MTV_PUBLIC VideoDisplayProfile
     static QString     GetDecoderName(const QString &decoder);
     static QString     GetDecoderHelp(QString decoder = QString::null);
 
-    static QString     GetDefaultProfileName(const QString &hostname);
+    static QString     GetDefaultProfileName(const QString &hostname,
+                                             PlaySettings *settings);
     static void        SetDefaultProfileName(const QString &profilename,
                                              const QString &hostname);
     static uint        GetProfileGroupID(const QString &profilename,
diff --git a/mythtv/libs/libmythtv/videoout_d3d.cpp b/mythtv/libs/libmythtv/videoout_d3d.cpp
index 5a6f917..312ec51 100644
--- a/mythtv/libs/libmythtv/videoout_d3d.cpp
+++ b/mythtv/libs/libmythtv/videoout_d3d.cpp
@@ -56,8 +56,8 @@ void VideoOutputD3D::GetRenderOptions(render_opts &opts,
 #endif
 }
 
-VideoOutputD3D::VideoOutputD3D(void)
-  : VideoOutput(),         m_lock(QMutex::Recursive),
+VideoOutputD3D::VideoOutputD3D(PlaySettigns *settings)
+  : VideoOutput(settings), m_lock(QMutex::Recursive),
     m_hWnd(NULL),          m_render(NULL),
     m_video(NULL),
     m_render_valid(false), m_render_reset(false), m_pip_active(NULL),
diff --git a/mythtv/libs/libmythtv/videoout_d3d.h b/mythtv/libs/libmythtv/videoout_d3d.h
index 1dcff21..3c31774 100644
--- a/mythtv/libs/libmythtv/videoout_d3d.h
+++ b/mythtv/libs/libmythtv/videoout_d3d.h
@@ -16,7 +16,7 @@ class VideoOutputD3D : public VideoOutput
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputD3D();
+    VideoOutputD3D(PlaySettings *settings);
    ~VideoOutputD3D();
 
     bool Init(int width, int height, float aspect,
diff --git a/mythtv/libs/libmythtv/videoout_null.cpp b/mythtv/libs/libmythtv/videoout_null.cpp
index 9d51f7c..c78b4b1 100644
--- a/mythtv/libs/libmythtv/videoout_null.cpp
+++ b/mythtv/libs/libmythtv/videoout_null.cpp
@@ -28,8 +28,8 @@ void VideoOutputNull::GetRenderOptions(render_opts &opts,
     opts.priorities->insert("null", 10);
 }
 
-VideoOutputNull::VideoOutputNull() :
-    VideoOutput(), global_lock(QMutex::Recursive)
+VideoOutputNull::VideoOutputNull(PlaySettings *settings) :
+    VideoOutput(settings), global_lock(QMutex::Recursive)
 {
     LOG(VB_PLAYBACK, LOG_INFO, "VideoOutputNull()");
     memset(&av_pause_frame, 0, sizeof(av_pause_frame));
diff --git a/mythtv/libs/libmythtv/videoout_null.h b/mythtv/libs/libmythtv/videoout_null.h
index d7a6747..20a6a12 100644
--- a/mythtv/libs/libmythtv/videoout_null.h
+++ b/mythtv/libs/libmythtv/videoout_null.h
@@ -9,7 +9,7 @@ class VideoOutputNull : public VideoOutput
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputNull();
+    VideoOutputNull(PlaySettings *settings);
    ~VideoOutputNull();
 
     bool Init(int width, int height, float aspect,
diff --git a/mythtv/libs/libmythtv/videoout_opengl.cpp b/mythtv/libs/libmythtv/videoout_opengl.cpp
index 8d89a10..14a8d2b 100644
--- a/mythtv/libs/libmythtv/videoout_opengl.cpp
+++ b/mythtv/libs/libmythtv/videoout_opengl.cpp
@@ -38,8 +38,8 @@ void VideoOutputOpenGL::GetRenderOptions(render_opts &opts,
     opts.priorities->insert("opengl", 65);
 }
 
-VideoOutputOpenGL::VideoOutputOpenGL()
-    : VideoOutput(),
+VideoOutputOpenGL::VideoOutputOpenGL(PlaySettings *settings)
+    : VideoOutput(settings),
     gl_context_lock(QMutex::Recursive), gl_context(NULL), gl_valid(true),
     gl_videochain(NULL), gl_pipchain_active(NULL),
     gl_parent_win(0),    gl_painter(NULL), gl_created_painter(false)
diff --git a/mythtv/libs/libmythtv/videoout_opengl.h b/mythtv/libs/libmythtv/videoout_opengl.h
index 7fce601..545c446 100644
--- a/mythtv/libs/libmythtv/videoout_opengl.h
+++ b/mythtv/libs/libmythtv/videoout_opengl.h
@@ -10,7 +10,7 @@ class VideoOutputOpenGL : public VideoOutput
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputOpenGL();
+    VideoOutputOpenGL(PlaySettings *settings);
     virtual ~VideoOutputOpenGL();
 
     virtual bool Init(int width, int height, float aspect,
diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.cpp b/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
index 92d8d0f..afc3b53 100644
--- a/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
+++ b/mythtv/libs/libmythtv/videoout_openglvaapi.cpp
@@ -25,8 +25,8 @@ void VideoOutputOpenGLVAAPI::GetRenderOptions(render_opts &opts)
     opts.priorities->insert("openglvaapi", 120);
 }
 
-VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI()
-  : VideoOutputOpenGL(), m_ctx(NULL), m_pauseBuffer(NULL)
+VideoOutputOpenGLVAAPI::VideoOutputOpenGLVAAPI(PlaySettings *settings)
+  : VideoOutputOpenGL(settings), m_ctx(NULL), m_pauseBuffer(NULL)
 {
 }
 
diff --git a/mythtv/libs/libmythtv/videoout_openglvaapi.h b/mythtv/libs/libmythtv/videoout_openglvaapi.h
index 2650095..915113d 100644
--- a/mythtv/libs/libmythtv/videoout_openglvaapi.h
+++ b/mythtv/libs/libmythtv/videoout_openglvaapi.h
@@ -10,7 +10,7 @@ class VideoOutputOpenGLVAAPI : public VideoOutputOpenGL
   public:
     static void GetRenderOptions(render_opts &opts);
 
-    VideoOutputOpenGLVAAPI();
+    VideoOutputOpenGLVAAPI(PlaySettings *settings);
    ~VideoOutputOpenGLVAAPI();
 
     bool  Init(int width, int height, float aspect, WId winid,
diff --git a/mythtv/libs/libmythtv/videoout_quartz.cpp b/mythtv/libs/libmythtv/videoout_quartz.cpp
index 85838d7..44fdb5b 100644
--- a/mythtv/libs/libmythtv/videoout_quartz.cpp
+++ b/mythtv/libs/libmythtv/videoout_quartz.cpp
@@ -66,6 +66,8 @@ using namespace std;
 #include "mythlogging.h"
 #include "videodisplayprofile.h"
 
+class PlaySettings;
+
 #define LOC     QString("VideoOutputQuartz::")
 #define LOC_ERR QString("VideoOutputQuartz Error: ")
 
@@ -1107,8 +1109,8 @@ void VideoOutputQuartz::GetRenderOptions(render_opts &opts,
 /** \class VideoOutputQuartz
  *  \brief Implementation of Quartz (Mac OS X windowing system) video output
  */
-VideoOutputQuartz::VideoOutputQuartz() :
-    VideoOutput(), Started(false), data(new QuartzData())
+VideoOutputQuartz::VideoOutputQuartz(PlaySettings *settings) :
+    VideoOutput(settings), Started(false), data(new QuartzData())
 {
     init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
 }
@@ -1757,12 +1759,12 @@ QStringList VideoOutputQuartz::GetAllowedRenderers(
 MythCodecID VideoOutputQuartz::GetBestSupportedCodec(
     uint width, uint height,
     uint osd_width, uint osd_height,
-    uint stream_type, uint fourcc)
+    uint stream_type, uint fourcc, PlaySettings *settings)
 {
     (void) osd_width;
     (void) osd_height;
 
-    VideoDisplayProfile vdp;
+    VideoDisplayProfile vdp(settings);
     vdp.SetInput(QSize(width, height));
     QString dec = vdp.GetDecoder();
     if (dec == "ffmpeg")
diff --git a/mythtv/libs/libmythtv/videoout_quartz.h b/mythtv/libs/libmythtv/videoout_quartz.h
index 6b2a4ee..640fddf 100644
--- a/mythtv/libs/libmythtv/videoout_quartz.h
+++ b/mythtv/libs/libmythtv/videoout_quartz.h
@@ -2,6 +2,7 @@
 #define VIDEOOUT_QUARTZ_H_
 
 struct QuartzData;
+class PlaySettings;
 
 #include "videooutbase.h"
 
@@ -9,7 +10,7 @@ class VideoOutputQuartz : public VideoOutput
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputQuartz();
+    VideoOutputQuartz(PlaySettings *settings);
    ~VideoOutputQuartz();
 
     bool Init(int width, int height, float aspect, WId winid,
@@ -51,7 +52,7 @@ class VideoOutputQuartz : public VideoOutput
     static MythCodecID GetBestSupportedCodec(
         uint width, uint height,
         uint osd_width, uint osd_height,
-        uint stream_type, uint fourcc);
+        uint stream_type, uint fourcc, PlaySettings *settings);
     virtual bool NeedExtraAudioDecode(void) const
         { return !codec_is_std(video_codec_id); }
 
diff --git a/mythtv/libs/libmythtv/videoout_vdpau.cpp b/mythtv/libs/libmythtv/videoout_vdpau.cpp
index fd10407..b2207ac 100644
--- a/mythtv/libs/libmythtv/videoout_vdpau.cpp
+++ b/mythtv/libs/libmythtv/videoout_vdpau.cpp
@@ -52,8 +52,8 @@ void VideoOutputVDPAU::GetRenderOptions(render_opts &opts)
     opts.deints->insert("vdpau", deints);
 }
 
-VideoOutputVDPAU::VideoOutputVDPAU()
-  : m_win(0),                m_render(NULL),
+VideoOutputVDPAU::VideoOutputVDPAU(PlaySettings *settings)
+  : VideoOutput(settings), m_win(0),           m_render(NULL),
     m_decoder_buffer_size(MAX_REFERENCE_FRAMES),
     m_process_buffer_size(DEF_PROCESS_BUFFER), m_pause_surface(0),
     m_need_deintrefs(false), m_video_mixer(0), m_mixer_features(kVDPFeatNone),
@@ -897,10 +897,10 @@ QStringList VideoOutputVDPAU::GetAllowedRenderers(
 
 MythCodecID VideoOutputVDPAU::GetBestSupportedCodec(
     uint width,       uint height,
-    uint stream_type, bool no_acceleration)
+    uint stream_type, bool no_acceleration, PlaySettings *settings)
 {
     bool use_cpu = no_acceleration;
-    VideoDisplayProfile vdp;
+    VideoDisplayProfile vdp(settings);
     vdp.SetInput(QSize(width, height));
     QString dec = vdp.GetDecoder();
 
diff --git a/mythtv/libs/libmythtv/videoout_vdpau.h b/mythtv/libs/libmythtv/videoout_vdpau.h
index 2404bb3..5de1064 100644
--- a/mythtv/libs/libmythtv/videoout_vdpau.h
+++ b/mythtv/libs/libmythtv/videoout_vdpau.h
@@ -20,7 +20,7 @@ class VideoOutputVDPAU : public VideoOutput
 {
   public:
     static void GetRenderOptions(render_opts &opts);
-    VideoOutputVDPAU();
+    VideoOutputVDPAU(PlaySettings *settings);
     ~VideoOutputVDPAU();
     bool Init(int width, int height, float aspect,
               WId winid, const QRect &win_rect, MythCodecID codec_id);
@@ -53,7 +53,8 @@ class VideoOutputVDPAU : public VideoOutput
                                     const QSize &video_dim);
     static MythCodecID GetBestSupportedCodec(uint width, uint height,
                                              uint stream_type,
-                                             bool no_acceleration);
+                                             bool no_acceleration,
+                                             PlaySettings *settings);
     virtual bool IsPIPSupported(void) const { return true;  }
     virtual bool IsPBPSupported(void) const { return false; }
     virtual bool NeedExtraAudioDecode(void) const
diff --git a/mythtv/libs/libmythtv/videoout_xv.cpp b/mythtv/libs/libmythtv/videoout_xv.cpp
index 345075a..8557538 100644
--- a/mythtv/libs/libmythtv/videoout_xv.cpp
+++ b/mythtv/libs/libmythtv/videoout_xv.cpp
@@ -136,8 +136,8 @@ void VideoOutputXv::GetRenderOptions(render_opts &opts,
  * \see VideoOutput, VideoBuffers
  *
  */
-VideoOutputXv::VideoOutputXv()
-    : VideoOutput(),
+VideoOutputXv::VideoOutputXv(PlaySettings *settings)
+    : VideoOutput(settings),
       video_output_subtype(XVUnknown),
       global_lock(QMutex::Recursive),
 
@@ -357,6 +357,7 @@ void VideoOutputXv::UngrabXvPort(MythXDisplay *disp, int port)
  * \return port number if it succeeds, else -1.
  */
 int VideoOutputXv::GrabSuitableXvPort(MythXDisplay* disp, Window root,
+                                      PlaySettings *settings,
                                       MythCodecID mcodecid,
                                       uint width, uint height,
                                       bool &xvsetdefaults,
@@ -381,7 +382,7 @@ int VideoOutputXv::GrabSuitableXvPort(MythXDisplay* disp, Window root,
     }
 
     // figure out if we want chromakeying..
-    VideoDisplayProfile vdp;
+    VideoDisplayProfile vdp(settings);
     vdp.SetInput(QSize(width, height));
     if (vdp.GetOSDRenderer() == "chromakey")
     {
@@ -594,7 +595,7 @@ bool VideoOutputXv::InitXVideo()
     disp->StartLog();
     QString adaptor_name = QString::null;
     const QSize video_dim = window.GetVideoDim();
-    xv_port = GrabSuitableXvPort(disp, disp->GetRoot(), kCodec_MPEG2,
+    xv_port = GrabSuitableXvPort(disp, disp->GetRoot(), settings, kCodec_MPEG2,
                                  video_dim.width(), video_dim.height(),
                                  xv_set_defaults, &adaptor_name);
     if (xv_port == -1)
diff --git a/mythtv/libs/libmythtv/videoout_xv.h b/mythtv/libs/libmythtv/videoout_xv.h
index befbcdd..df0544b 100644
--- a/mythtv/libs/libmythtv/videoout_xv.h
+++ b/mythtv/libs/libmythtv/videoout_xv.h
@@ -30,7 +30,7 @@ class VideoOutputXv : public VideoOutput
     friend class ChromaKeyOSD;
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputXv();
+    VideoOutputXv(PlaySettings *settings);
    ~VideoOutputXv();
 
     bool Init(int width, int height, float aspect,
@@ -81,6 +81,7 @@ class VideoOutputXv : public VideoOutput
     static MythCodecID GetBestSupportedCodec(uint stream_type);
 
     static int GrabSuitableXvPort(MythXDisplay* disp, Window root,
+                                  PlaySettings *settings,
                                   MythCodecID type,
                                   uint width, uint height,
                                   bool &xvsetdefaults,
diff --git a/mythtv/libs/libmythtv/videooutbase.cpp b/mythtv/libs/libmythtv/videooutbase.cpp
index 162ad92..68fa831 100644
--- a/mythtv/libs/libmythtv/videooutbase.cpp
+++ b/mythtv/libs/libmythtv/videooutbase.cpp
@@ -7,6 +7,7 @@
 #include "mythplayer.h"
 #include "videodisplayprofile.h"
 #include "decoderbase.h"
+#include "playsettings.h"
 
 #include "mythcorecontext.h"
 #include "mythlogging.h"
@@ -106,7 +107,7 @@ void VideoOutput::GetRenderOptions(render_opts &opts)
 VideoOutput *VideoOutput::Create(
     const QString &decoder, MythCodecID  codec_id,     void *codec_priv,
     PIPState pipState,      const QSize &video_dim,    float video_aspect,
-    WId win_id,             const QRect &display_rect, float video_prate)
+    WId win_id,             const QRect &display_rect, float video_prate, PlaySettings *settings)
 {
     (void) codec_priv;
 
@@ -151,7 +152,7 @@ VideoOutput *VideoOutput::Create(
     QString renderer = QString::null;
     if (renderers.size() > 0)
     {
-        VideoDisplayProfile vprof;
+        VideoDisplayProfile vprof(settings);
         vprof.SetInput(video_dim);
 
         QString tmp = vprof.GetVideoRenderer();
@@ -179,32 +180,32 @@ VideoOutput *VideoOutput::Create(
 
 #ifdef USING_MINGW
         if (renderer == "direct3d")
-            vo = new VideoOutputD3D();
+            vo = new VideoOutputD3D(settings);
 #endif // USING_MINGW
 
 #ifdef USING_QUARTZ_VIDEO
         if (osxlist.contains(renderer))
-            vo = new VideoOutputQuartz();
+            vo = new VideoOutputQuartz(settings);
 #endif // Q_OS_MACX
 
 #ifdef USING_OPENGL_VIDEO
         if (renderer == "opengl")
-            vo = new VideoOutputOpenGL();
+            vo = new VideoOutputOpenGL(settings);
 #endif // USING_OPENGL_VIDEO
 
 #ifdef USING_VDPAU
         if (renderer == "vdpau")
-            vo = new VideoOutputVDPAU();
+            vo = new VideoOutputVDPAU(settings);
 #endif // USING_VDPAU
 
 #ifdef USING_VAAPI
         if (renderer == "openglvaapi")
-            vo = new VideoOutputOpenGLVAAPI();
+            vo = new VideoOutputOpenGLVAAPI(settings);
 #endif // USING_VAAPI
 
 #ifdef USING_XV
         if (xvlist.contains(renderer))
-            vo = new VideoOutputXv();
+            vo = new VideoOutputXv(settings);
 #endif // USING_XV
 
         if (vo)
@@ -300,8 +301,9 @@ VideoOutput *VideoOutput::Create(
  * \brief This constructor for VideoOutput must be followed by an
  *        Init(int,int,float,WId,int,int,int,int,WId) call.
  */
-VideoOutput::VideoOutput() :
+VideoOutput::VideoOutput(PlaySettings *_settings) :
     // DB Settings
+    window(_settings),
     db_display_dim(0,0),
     db_aspectoverride(kAspect_Off), db_adjustfill(kAdjustFill_Off),
     db_letterbox_colour(kLetterBoxColour_Black),
@@ -340,21 +342,23 @@ VideoOutput::VideoOutput() :
     osd_painter(NULL),                  osd_image(NULL),
 
     // Visualisation
-    m_visual(NULL)
+    m_visual(NULL),
+
+    settings(_settings)
 {
     memset(&pip_tmp_image, 0, sizeof(pip_tmp_image));
-    db_display_dim = QSize(gCoreContext->GetNumSetting("DisplaySizeWidth",  0),
-                           gCoreContext->GetNumSetting("DisplaySizeHeight", 0));
+    db_display_dim = QSize(settings->GetNumSetting("DisplaySizeWidth",  0),
+                           settings->GetNumSetting("DisplaySizeHeight", 0));
 
     db_aspectoverride = (AspectOverrideMode)
-        gCoreContext->GetNumSetting("AspectOverride",      0);
+        settings->GetNumSetting("AspectOverride",      0);
     db_adjustfill = (AdjustFillMode)
-        gCoreContext->GetNumSetting("AdjustFill",          0);
+        settings->GetNumSetting("AdjustFill",          0);
     db_letterbox_colour = (LetterBoxColour)
-        gCoreContext->GetNumSetting("LetterboxColour",     0);
+        settings->GetNumSetting("LetterboxColour",     0);
 
     if (!gCoreContext->IsDatabaseIgnored())
-        db_vdisp_profile = new VideoDisplayProfile();
+        db_vdisp_profile = new VideoDisplayProfile(settings);
 }
 
 /**
@@ -430,12 +434,12 @@ QString VideoOutput::GetFilters(void) const
     return QString::null;
 }
 
-bool VideoOutput::IsPreferredRenderer(QSize video_size)
+bool VideoOutput::IsPreferredRenderer(QSize video_size, PlaySettings *settings)
 {
     if (!db_vdisp_profile || (video_size == window.GetVideoDispDim()))
         return true;
 
-    VideoDisplayProfile vdisp;
+    VideoDisplayProfile vdisp(settings);
     vdisp.SetInput(video_size);
     QString new_rend = vdisp.GetVideoRenderer();
     if (new_rend.isEmpty())
diff --git a/mythtv/libs/libmythtv/videooutbase.h b/mythtv/libs/libmythtv/videooutbase.h
index 334d08c..e03f03d 100644
--- a/mythtv/libs/libmythtv/videooutbase.h
+++ b/mythtv/libs/libmythtv/videooutbase.h
@@ -36,6 +36,7 @@ class FilterChain;
 class FilterManager;
 class AudioPlayer;
 class MythRender;
+class PlaySettings;
 
 typedef QMap<MythPlayer*,PIPLocation> PIPMap;
 
@@ -51,16 +52,16 @@ class VideoOutput
     static VideoOutput *Create(
         const QString &decoder, MythCodecID  codec_id,     void *codec_priv,
         PIPState pipState,      const QSize &video_dim,    float video_aspect,
-        WId win_id,             const QRect &display_rect, float video_prate);
+        WId win_id,             const QRect &display_rect, float video_prate, PlaySettings *settings);
 
-    VideoOutput();
+    VideoOutput(PlaySettings *settings);
     virtual ~VideoOutput();
 
     virtual bool Init(int width, int height, float aspect,
                       WId winid, const QRect &win_rect, MythCodecID codec_id);
     virtual void InitOSD(OSD *osd);
     virtual void SetVideoFrameRate(float);
-    virtual bool IsPreferredRenderer(QSize video_size);
+    virtual bool IsPreferredRenderer(QSize video_size, PlaySettings *settings);
     virtual bool SetDeinterlacingEnabled(bool);
     virtual bool SetupDeinterlace(bool i, const QString& ovrf="");
     virtual void FallbackDeint(void);
@@ -333,6 +334,8 @@ class VideoOutput
 
     // Visualisation
     VideoVisual     *m_visual;
+
+    PlaySettings *settings;
 };
 
 #endif
diff --git a/mythtv/libs/libmythtv/videooutwindow.cpp b/mythtv/libs/libmythtv/videooutwindow.cpp
index e5bf183..c7a79f6 100644
--- a/mythtv/libs/libmythtv/videooutwindow.cpp
+++ b/mythtv/libs/libmythtv/videooutwindow.cpp
@@ -29,6 +29,7 @@
 
 #include "videooutwindow.h"
 #include "osd.h"
+#include "playsettings.h"
 #include "mythplayer.h"
 #include "videodisplayprofile.h"
 #include "decoderbase.h"
@@ -52,7 +53,7 @@ const float VideoOutWindow::kManualZoomMinHorizontalZoom = 0.5f;
 const float VideoOutWindow::kManualZoomMinVerticalZoom   = 0.5f;
 const int   VideoOutWindow::kManualZoomMaxMove           = 50;
 
-VideoOutWindow::VideoOutWindow() :
+VideoOutWindow::VideoOutWindow(PlaySettings *_settings) :
     // DB settings
     db_move(0, 0), db_scale_horiz(0.0f), db_scale_vert(0.0f),
     db_pip_size(26),
@@ -85,12 +86,14 @@ VideoOutWindow::VideoOutWindow() :
 
     // Various state variables
     embedding(false), needrepaint(false),
-    allowpreviewepg(true), pip_state(kPIPOff)
+    allowpreviewepg(true), pip_state(kPIPOff),
+
+    settings(_settings)
 {
     db_pip_size = gCoreContext->GetNumSetting("PIPSize", 26);
 
-    db_move = QPoint(gCoreContext->GetNumSetting("xScanDisplacement", 0),
-                     gCoreContext->GetNumSetting("yScanDisplacement", 0));
+    db_move = QPoint(settings->GetNumSetting("xScanDisplacement", 0),
+                     settings->GetNumSetting("yScanDisplacement", 0));
     db_use_gui_size = gCoreContext->GetNumSetting("GuiSizeForTV", 0);
 
     QDesktopWidget *desktop = NULL;
@@ -635,9 +638,9 @@ void VideoOutWindow::SetVideoScalingAllowed(bool change)
     if (change)
     {
         db_scale_vert =
-            gCoreContext->GetNumSetting("VertScanPercentage", 0) * 0.01f;
+            settings->GetNumSetting("VertScanPercentage", 0) * 0.01f;
         db_scale_horiz =
-            gCoreContext->GetNumSetting("HorizScanPercentage", 0) * 0.01f;
+            settings->GetNumSetting("HorizScanPercentage", 0) * 0.01f;
         db_scaling_allowed = true;
     }
     else
diff --git a/mythtv/libs/libmythtv/videooutwindow.h b/mythtv/libs/libmythtv/videooutwindow.h
index 017eede..1a26adb 100644
--- a/mythtv/libs/libmythtv/videooutwindow.h
+++ b/mythtv/libs/libmythtv/videooutwindow.h
@@ -16,11 +16,12 @@
 #include "videoouttypes.h"
 
 class MythPlayer;
+class PlaySettings;
 
 class VideoOutWindow
 {
   public:
-    VideoOutWindow();
+    VideoOutWindow(PlaySettings *settings);
 
     bool Init(const QSize &new_video_dim, float aspect,
               const QRect &new_display_visible_rect,
@@ -167,6 +168,8 @@ class VideoOutWindow
     bool     allowpreviewepg;
     PIPState pip_state;
 
+    PlaySettings *settings;
+
     // Constants
     static const float kManualZoomMaxHorizontalZoom;
     static const float kManualZoomMaxVerticalZoom;
diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
index 2c0a5df..5aa56f6 100644
--- a/mythtv/libs/libmythtv/vsync.cpp
+++ b/mythtv/libs/libmythtv/vsync.cpp
@@ -34,6 +34,7 @@
 
 #include "mythcontext.h"
 #include "mythmainwindow.h"
+#include "playsettings.h"
 
 #ifdef USING_XV
 #include "videoout_xv.h"
@@ -74,6 +75,7 @@ int VideoSync::m_forceskip = 0;
  *  \brief Returns the most sophisticated video sync method available.
  */
 VideoSync *VideoSync::BestMethod(VideoOutput *video_output,
+                                 PlaySettings *settings,
                                  uint frame_interval, uint refresh_interval,
                                  bool halve_frame_interval)
 {
diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
index 5764ddc..0961292 100644
--- a/mythtv/libs/libmythtv/vsync.h
+++ b/mythtv/libs/libmythtv/vsync.h
@@ -89,6 +89,7 @@ class VideoSync
 
     // documented in vsync.cpp
     static VideoSync *BestMethod(VideoOutput*,
+                                 PlaySettings *settings,
                                  uint frame_interval, uint refresh_interval,
                                  bool interlaced);
   protected:
diff --git a/mythtv/programs/mythavtest/main.cpp b/mythtv/programs/mythavtest/main.cpp
index 784f68e..388d550 100644
--- a/mythtv/programs/mythavtest/main.cpp
+++ b/mythtv/programs/mythavtest/main.cpp
@@ -20,6 +20,7 @@ using namespace std;
 #include "compat.h"
 #include "dbcheck.h"
 #include "mythlogging.h"
+#include "playsettings.h"
 
 // libmythui
 #include "mythuihelper.h"
@@ -122,18 +123,6 @@ int main(int argc, char *argv[])
 
     GetMythUI()->LoadQtConfig();
 
-#if defined(Q_OS_MACX)
-    // Mac OS X doesn't define the AudioOutputDevice setting
-#else
-    QString auddevice = gCoreContext->GetSetting("AudioOutputDevice");
-    if (auddevice.isEmpty())
-    {
-        LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Audio not configured, you need "
-                                 "to run 'mythfrontend', not 'mythtv'.");
-        return GENERIC_EXIT_SETUP_ERROR;
-    }
-#endif
-
     MythMainWindow *mainWindow = GetMythMainWindow();
     mainWindow->Init();
 
@@ -146,7 +135,27 @@ int main(int argc, char *argv[])
         return GENERIC_EXIT_DB_OUTOFDATE;
     }
 
-    TV *tv = new TV();
+    QString playgroup("");
+    if (!filename.isEmpty())
+    {
+        ProgramInfo pg(filename);
+        playgroup = pg.GetPlaybackGroup();
+    }
+    PlaySettings settings(playgroup);
+
+#if defined(Q_OS_MACX)
+    // Mac OS X doesn't define the AudioOutputDevice setting
+#else
+    QString auddevice = settings.GetSetting("AudioOutputDevice", "");
+    if (auddevice.isEmpty())
+    {
+        LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Audio not configured, you need "
+                                 "to run 'mythfrontend', not 'mythtv'.");
+        return GENERIC_EXIT_SETUP_ERROR;
+    }
+#endif
+
+    TV *tv = new TV(&settings);
     if (!tv->Init())
     {
         LOG(VB_GENERAL, LOG_ERR, "Fatal Error: Could not initialize TV class.");
diff --git a/mythtv/programs/mythfrontend/globalsettings.cpp b/mythtv/programs/mythfrontend/globalsettings.cpp
index 0763cc4..d0bb4bb 100644
--- a/mythtv/programs/mythfrontend/globalsettings.cpp
+++ b/mythtv/programs/mythfrontend/globalsettings.cpp
@@ -38,10 +38,125 @@
 #include "mythconfig.h"
 #include "mythdirs.h"
 #include "mythuihelper.h"
+#include "playsettings.h"
+
+#define CREATE_CHECKBOX_SETTING(var, name, settings) \
+    BooleanSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsCheckBox((name), (settings)); \
+    else \
+        var = new HostCheckBox((name))
+
+#define CREATE_COMBOBOX_SETTING(var, name, settings) \
+    ComboBoxSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsComboBox((name), (settings)); \
+    else \
+        var = new HostComboBox((name))
+
+#define CREATE_COMBOBOX1_SETTING(var, name, settings, arg1) \
+    ComboBoxSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsComboBox((name), (settings), (arg1)); \
+    else \
+        var = new HostComboBox((name), (arg1))
+
+#define CREATE_SPINBOX_SETTING(var, name, settings, arg1, arg2, arg3, arg4) \
+    SpinBoxSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsSpinBox((name), (settings), (arg1), (arg2), (arg3), (arg4)); \
+    else \
+        var = new HostSpinBox((name), (arg1), (arg2), (arg3), (arg4))
+
+#define CREATE_LINEEDIT_SETTING(var, name, settings) \
+    LineEditSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsLineEdit((name), (settings), ""); \
+    else \
+        var = new HostLineEdit((name))
+
+// For PlaySettings, use a SpinBox instead of a Slider so that a
+// default value can be easily used.
+#define CREATE_SLIDER_SETTING(var, name, settings, arg1, arg2, arg3) \
+    BoundedIntegerSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsSpinBox((name), (settings), (arg1), (arg2), (arg3)); \
+    else \
+        var = new HostSlider((name), (arg1), (arg2), (arg3))
+
+#define CREATE_IMAGESELECT_SETTING(var, name, settings) \
+    ImageSelectSetting *var; \
+    if ((settings)) \
+        var = new PlaySettingsImageSelect((name), (settings)); \
+    else \
+        var = new HostImageSelect((name))
+
+static Setting *wrap(Setting *obj, PlaySettings *settings,
+                     bool twoLineLabel=false)
+{
+    if (!settings)
+        return obj;
+
+    // Get the setting name
+    PlaySettingsCombinedStorage *storage =
+        dynamic_cast<PlaySettingsCombinedStorage *>(obj);
+    const QString &name = storage->getName();
+
+    // Get the default value and label.  The label is  different
+    // from the value for most object types.
+    QString defaultValue = settings->GetSetting(name, "", true);
+    QString defaultLabel(defaultValue);
+    if (dynamic_cast<BooleanSetting *>(obj))
+        defaultLabel = (defaultValue == "0" || defaultValue.isEmpty() ?
+                        QObject::tr("disabled") : QObject::tr("enabled"));
+    if (dynamic_cast<SpinBoxSetting *>(obj) && defaultValue.isEmpty())
+        defaultLabel = "0";
+    ComboBoxSetting *cb = dynamic_cast<ComboBoxSetting *>(obj);
+    if (cb)
+    {
+        defaultLabel = cb->GetValueLabel(defaultValue);
+        // Add the default selection to a ComboBox
+        cb->addSelection(QString("(") + QObject::tr("default") + ")",
+                         storage->getDefault(),
+                         !settings->IsOverridden(name),
+                         true);
+    }
+    ImageSelectSetting *is = dynamic_cast<ImageSelectSetting *>(obj);
+    if (is)
+    {
+        defaultLabel = is->GetValueLabel(defaultValue);
+        // Add the default selection to a ImageSelect
+        is->addDefaultSelection(QString("(") + QObject::tr("default") + ")",
+                                storage->getDefault(),
+                                defaultValue,
+                                !settings->IsOverridden(name));
+    }
+
+    // Change the help text to include the default and its source.
+    QString helpPrefix;
+    if (dynamic_cast<LineEditSetting *>(obj))
+        helpPrefix = QObject::tr("Leave blank to keep default value");
+    else
+        helpPrefix = QObject::tr("Override default value");
+    helpPrefix += " (" + defaultLabel + ") ";
+    QString inheritsFrom = settings->InheritsFrom(name);
+    if (inheritsFrom.isNull())
+        helpPrefix += QObject::tr("from global settings");
+    else
+        helpPrefix += QObject::tr("from group") + " " + inheritsFrom;
+    helpPrefix += ". " + obj->getHelpText();
+    obj->setHelpText(helpPrefix);
+
+    // Change the label to include the default.
+    obj->setLabel(obj->getLabel() + (twoLineLabel ? "\n" : "") +
+                  " (" + defaultLabel + ")");
 
-static HostCheckBox *DecodeExtraAudio()
+    return obj;
+}
+
+static Setting *DecodeExtraAudio(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("DecodeExtraAudio");
+    CREATE_CHECKBOX_SETTING(gc, "DecodeExtraAudio", settings);
     gc->setLabel(QObject::tr("Extra audio buffering"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("Enable this setting if MythTV is playing "
@@ -50,17 +165,17 @@ static HostCheckBox *DecodeExtraAudio()
                     "effect on framegrabbers (MPEG-4/RTJPEG). MythTV will "
                     "keep extra audio data in its internal buffers to "
                     "workaround this bug."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *PIPLocationComboBox()
+static Setting *PIPLocationComboBox(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("PIPLocation");
+    CREATE_COMBOBOX_SETTING(gc, "PIPLocation", settings);
     gc->setLabel(QObject::tr("PIP video location"));
     for (uint loc = 0; loc < kPIP_END; ++loc)
         gc->addSelection(toString((PIPLocation) loc), QString::number(loc));
     gc->setHelpText(QObject::tr("Location of PIP Video window."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostComboBox *DisplayRecGroup()
@@ -146,25 +261,25 @@ static HostCheckBox *PBBStartInTitle()
     return gc;
 }
 
-static HostCheckBox *SmartForward()
+static Setting *SmartForward(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("SmartForward");
+    CREATE_CHECKBOX_SETTING(gc, "SmartForward", settings);
     gc->setLabel(QObject::tr("Smart fast forwarding"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("If enabled, then immediately after "
                     "rewinding, only skip forward the same amount as "
                     "skipping backwards."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *ExactSeeking()
+static Setting *ExactSeeking(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("ExactSeeking");
+    CREATE_CHECKBOX_SETTING(gc, "ExactSeeking", settings);
     gc->setLabel(QObject::tr("Seek to exact frame"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("If enabled, seeking is frame exact, but "
                     "slower."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static GlobalComboBox *CommercialSkipMethod()
@@ -192,9 +307,9 @@ static GlobalCheckBox *CommFlagFast()
     return gc;
 }
 
-static HostComboBox *AutoCommercialSkip()
+static Setting *AutoCommercialSkip(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("AutoCommercialSkip");
+    CREATE_COMBOBOX_SETTING(gc, "AutoCommercialSkip", settings);
     gc->setLabel(QObject::tr("Automatically skip commercials"));
     gc->addSelection(QObject::tr("Off"), "0");
     gc->addSelection(QObject::tr("Notify, but do not skip"), "2");
@@ -203,7 +318,7 @@ static HostComboBox *AutoCommercialSkip()
                     "have been flagged during automatic commercial detection "
                     "or by the mythcommflag program, or just notify that a "
                     "commercial has been detected."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static GlobalCheckBox *AutoMetadataLookup()
@@ -277,26 +392,26 @@ static GlobalCheckBox *AggressiveCommDetect()
     return bc;
 }
 
-static HostSpinBox *CommRewindAmount()
+static Setting *CommRewindAmount(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("CommRewindAmount", 0, 10, 1);
+    CREATE_SPINBOX_SETTING(gs, "CommRewindAmount", settings, 0, 10, 1, false);
     gs->setLabel(QObject::tr("Commercial skip automatic rewind amount (secs)"));
     gs->setHelpText(QObject::tr("MythTV will automatically rewind "
                     "this many seconds after performing a commercial skip."));
     gs->setValue(0);
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSpinBox *CommNotifyAmount()
+static Setting *CommNotifyAmount(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("CommNotifyAmount", 0, 10, 1);
+    CREATE_SPINBOX_SETTING(gs, "CommNotifyAmount", settings, 0, 10, 1, false);
     gs->setLabel(QObject::tr("Commercial skip notify amount (secs)"));
     gs->setHelpText(QObject::tr("MythTV will act like a commercial "
                     "begins this many seconds early. This can be useful "
                     "when commercial notification is used in place of "
                     "automatic skipping."));
     gs->setValue(0);
-    return gs;
+    return wrap(gs, settings);
 }
 
 static GlobalSpinBox *MaximumCommercialSkip()
@@ -1098,11 +1213,16 @@ void PlaybackProfileConfig::swap(int i, int j)
     labels[j]->setValue(label_i);
 }
 
-PlaybackProfileConfigs::PlaybackProfileConfigs(const QString &str) :
+PlaybackProfileConfigs::PlaybackProfileConfigs(const QString &str,
+                                               PlaySettings *settings) :
     TriggeredConfigurationGroup(false, true,  true, true,
                                 false, false, true, true), grouptrigger(NULL)
 {
     setLabel(QObject::tr("Playback Profiles") + str);
+    if (settings)
+        setLabel(QObject::tr("Playback group settings for ") +
+                 settings->mGroupName + " - " +
+                 getLabel());
 
     QString host = gCoreContext->GetHostName();
     QStringList profiles = VideoDisplayProfile::GetProfiles(host);
@@ -1130,18 +1250,24 @@ PlaybackProfileConfigs::PlaybackProfileConfigs(const QString &str) :
         profiles = VideoDisplayProfile::GetProfiles(host);
     }
 
-    QString profile = VideoDisplayProfile::GetDefaultProfileName(host);
+    QString profile = VideoDisplayProfile::GetDefaultProfileName(host, settings);
     if (!profiles.contains(profile))
     {
         profile = (profiles.contains("Normal")) ? "Normal" : profiles[0];
         VideoDisplayProfile::SetDefaultProfileName(profile, host);
     }
 
-    grouptrigger = new HostComboBox("DefaultVideoPlaybackProfile");
+    CREATE_COMBOBOX_SETTING(gs, "DefaultVideoPlaybackProfile", settings);
+    grouptrigger = gs;
     grouptrigger->setLabel(QObject::tr("Current Video Playback Profile"));
     QStringList::const_iterator it;
     for (it = profiles.begin(); it != profiles.end(); ++it)
         grouptrigger->addSelection(ProgramInfo::i18n(*it), *it);
+    if (settings)
+    {
+        addChild(wrap(grouptrigger, settings));
+        return;
+    }
 
     HorizontalConfigurationGroup *grp =
         new HorizontalConfigurationGroup(false, false, true, true);
@@ -1274,9 +1400,9 @@ static HostComboBox *PlayBoxEpisodeSort()
     return gc;
 }
 
-static HostSpinBox *FFRewReposTime()
+static Setting *FFRewReposTime(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("FFRewReposTime", 0, 200, 5);
+    CREATE_SPINBOX_SETTING(gs, "FFRewReposTime", settings, 0, 200, 5, false);
     gs->setLabel(QObject::tr("Fast forward/rewind reposition amount"));
     gs->setValue(100);
     gs->setHelpText(QObject::tr("When exiting sticky keys fast forward/rewind "
@@ -1284,12 +1410,12 @@ static HostSpinBox *FFRewReposTime()
                     "resuming normal playback. This "
                     "compensates for the reaction time between seeing "
                     "where to resume playback and actually exiting seeking."));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostCheckBox *FFRewReverse()
+static Setting *FFRewReverse(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("FFRewReverse");
+    CREATE_CHECKBOX_SETTING(gc, "FFRewReverse", settings);
     gc->setLabel(QObject::tr("Reverse direction in fast forward/rewind"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("If enabled, pressing the sticky rewind key "
@@ -1297,7 +1423,7 @@ static HostCheckBox *FFRewReverse()
                     "vice versa. If disabled, it will decrease the "
                     "current speed or switch to play mode if "
                     "the speed can't be decreased further."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostComboBox *MenuTheme()
@@ -1334,14 +1460,15 @@ static HostComboBox MUNUSED *DecodeVBIFormat()
     return gc;
 }
 
-static HostSpinBox *OSDCC708TextZoomPercentage(void)
+static Setting *OSDCC708TextZoomPercentage(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("OSDCC708TextZoom", 50, 200, 5);
+    CREATE_SPINBOX_SETTING(gs, "OSDCC708TextZoom", settings,
+                           50, 200, 5, false);
     gs->setLabel(QObject::tr("Subtitle text zoom percentage"));
     gs->setValue(100);
     gs->setHelpText(QObject::tr("Use this to enlarge or shrink text based subtitles."));
 
-    return gs;
+    return wrap(gs, settings);
 }
 
 static HostComboBox *SubtitleFont()
@@ -1361,9 +1488,9 @@ static HostComboBox *SubtitleFont()
     return hcb;
 }
 
-static HostComboBox *SubtitleCodec()
+static Setting *SubtitleCodec(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("SubtitleCodec");
+    CREATE_COMBOBOX_SETTING(gc, "SubtitleCodec", settings);
 
     gc->setLabel(QObject::tr("Subtitle Codec"));
     QList<QByteArray> list = QTextCodec::availableCodecs();
@@ -1373,7 +1500,7 @@ static HostComboBox *SubtitleCodec()
         gc->addSelection(val, val, val.toLower() == "utf-8");
     }
 
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostComboBox *ChannelOrdering()
@@ -1385,61 +1512,65 @@ static HostComboBox *ChannelOrdering()
     return gc;
 }
 
-static HostSpinBox *VertScanPercentage()
+static Setting *VertScanPercentage(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("VertScanPercentage", -100, 100, 1);
+    CREATE_SPINBOX_SETTING(gs, "VertScanPercentage", settings,
+                           -100, 100, 1, false);
     gs->setLabel(QObject::tr("Vertical scaling"));
     gs->setValue(0);
     gs->setHelpText(QObject::tr(
                         "Adjust this if the image does not fill your "
                         "screen vertically. Range -100% to 100%"));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSpinBox *HorizScanPercentage()
+static Setting *HorizScanPercentage(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("HorizScanPercentage", -100, 100, 1);
+    CREATE_SPINBOX_SETTING(gs, "HorizScanPercentage", settings,
+                           -100, 100, 1, false);
     gs->setLabel(QObject::tr("Horizontal scaling"));
     gs->setValue(0);
     gs->setHelpText(QObject::tr(
                         "Adjust this if the image does not fill your "
                         "screen horizontally. Range -100% to 100%"));
-    return gs;
+    return wrap(gs, settings);
 };
 
-static HostSpinBox *XScanDisplacement()
+static Setting *XScanDisplacement(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("XScanDisplacement", -50, 50, 1);
+    CREATE_SPINBOX_SETTING(gs, "XScanDisplacement", settings,
+                           -50, 50, 1, false);
     gs->setLabel(QObject::tr("Scan displacement (X)"));
     gs->setValue(0);
     gs->setHelpText(QObject::tr("Adjust this to move the image horizontally."));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSpinBox *YScanDisplacement()
+static Setting *YScanDisplacement(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("YScanDisplacement", -50, 50, 1);
+    CREATE_SPINBOX_SETTING(gs, "YScanDisplacement", settings,
+                           -50, 50, 1, false);
     gs->setLabel(QObject::tr("Scan displacement (Y)"));
     gs->setValue(0);
     gs->setHelpText(QObject::tr("Adjust this to move the image vertically."));
-    return gs;
+    return wrap(gs, settings);
 };
 
-static HostCheckBox *CCBackground()
+static Setting *CCBackground(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("CCBackground");
+    CREATE_CHECKBOX_SETTING(gc, "CCBackground", settings);
     gc->setLabel(QObject::tr("Black background for closed captioning"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr(
                         "If enabled, captions will be displayed "
                         "as white text over a black background "
                         "for better contrast."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *DefaultCCMode()
+static Setting *DefaultCCMode(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("DefaultCCMode");
+    CREATE_CHECKBOX_SETTING(gc, "DefaultCCMode", settings);
     gc->setLabel(QObject::tr("Always display closed captioning or subtitles"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr(
@@ -1447,12 +1578,12 @@ static HostCheckBox *DefaultCCMode()
                         "when playing back recordings or watching "
                         "Live TV. Closed Captioning can be turned on or off "
                         "by pressing \"T\" during playback."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *PreferCC708()
+static Setting *PreferCC708(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("Prefer708Captions");
+    CREATE_CHECKBOX_SETTING(gc, "Prefer708Captions", settings);
     gc->setLabel(QObject::tr("Prefer EIA-708 over EIA-608 captions"));
     gc->setValue(true);
     gc->setHelpText(
@@ -1460,36 +1591,36 @@ static HostCheckBox *PreferCC708()
             "If enabled, the newer EIA-708 captions will be preferred over "
             "the older EIA-608 captions in ATSC streams."));
 
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *EnableMHEG()
+static Setting *EnableMHEG(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("EnableMHEG");
+    CREATE_CHECKBOX_SETTING(gc, "EnableMHEG", settings);
     gc->setLabel(QObject::tr("Enable interactive TV"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr(
                         "If enabled, interactive TV applications (MHEG) will "
                         "be activated. This is used for teletext and logos for "
                         "radio and channels that are currently off-air."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *PersistentBrowseMode()
+static Setting *PersistentBrowseMode(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("PersistentBrowseMode");
+    CREATE_CHECKBOX_SETTING(gc, "PersistentBrowseMode", settings);
     gc->setLabel(QObject::tr("Always use browse mode in Live TV"));
     gc->setValue(true);
     gc->setHelpText(
         QObject::tr(
             "If enabled, browse mode will automatically be activated "
             "whenever you use channel up/down while watching Live TV."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *BrowseAllTuners()
+static Setting *BrowseAllTuners(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("BrowseAllTuners");
+    CREATE_CHECKBOX_SETTING(gc, "BrowseAllTuners", settings);
     gc->setLabel(QObject::tr("Browse all channels"));
     gc->setValue(false);
     gc->setHelpText(
@@ -1497,24 +1628,24 @@ static HostCheckBox *BrowseAllTuners()
             "If enabled, browse mode will shows channels on all "
             "available recording devices, instead of showing "
             "channels on just the current recorder."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *ClearSavedPosition()
+static Setting *ClearSavedPosition(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("ClearSavedPosition");
+    CREATE_CHECKBOX_SETTING(gc, "ClearSavedPosition", settings);
     gc->setLabel(QObject::tr("Clear bookmark on playback"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("If enabled, automatically clear the "
                     "bookmark on a recording when the recording is played "
                     "back. If disabled, you can mark the beginning with "
                     "rewind then save position."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AltClearSavedPosition()
+static Setting *AltClearSavedPosition(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AltClearSavedPosition");
+    CREATE_CHECKBOX_SETTING(gc, "AltClearSavedPosition", settings);
     gc->setLabel(QObject::tr("Alternate clear and save bookmark"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("During playback the SELECT key "
@@ -1522,12 +1653,12 @@ static HostCheckBox *AltClearSavedPosition()
                     "Saved\" and \"Bookmark Cleared\". If disabled, the "
                     "SELECT key will save the current position for each "
                     "keypress."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *PlaybackExitPrompt()
+static Setting *PlaybackExitPrompt(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("PlaybackExitPrompt");
+    CREATE_COMBOBOX_SETTING(gc, "PlaybackExitPrompt", settings);
     gc->setLabel(QObject::tr("Action on playback exit"));
     gc->addSelection(QObject::tr("Just exit"), "0");
     gc->addSelection(QObject::tr("Save position and exit"), "2");
@@ -1538,23 +1669,23 @@ static HostComboBox *PlaybackExitPrompt()
                     "when you exit playback mode. The options available will "
                     "allow you to save your position, delete the "
                     "recording, or continue watching."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *EndOfRecordingExitPrompt()
+static Setting *EndOfRecordingExitPrompt(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("EndOfRecordingExitPrompt");
+    CREATE_CHECKBOX_SETTING(gc, "EndOfRecordingExitPrompt", settings);
     gc->setLabel(QObject::tr("Prompt at end of recording"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("If enabled, a menu will be displayed allowing "
                     "you to delete the recording when it has finished "
                     "playing."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *JumpToProgramOSD()
+static Setting *JumpToProgramOSD(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("JumpToProgramOSD");
+    CREATE_CHECKBOX_SETTING(gc, "JumpToProgramOSD", settings);
     gc->setLabel(QObject::tr("Jump to program OSD"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr(
@@ -1563,12 +1694,12 @@ static HostCheckBox *JumpToProgramOSD()
                         "'Watch Recording' screen when 'Jump to Program' "
                         "is activated. If enabled, the recordings are shown "
                         "in the OSD"));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *ContinueEmbeddedTVPlay()
+static Setting *ContinueEmbeddedTVPlay(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("ContinueEmbeddedTVPlay");
+    CREATE_CHECKBOX_SETTING(gc, "ContinueEmbeddedTVPlay", settings);
     gc->setLabel(QObject::tr("Continue playback when embedded"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr(
@@ -1576,12 +1707,12 @@ static HostCheckBox *ContinueEmbeddedTVPlay()
                     "is embedded in the upcoming program list or recorded "
                     "list. The default is to pause the recorded show when "
                     "embedded."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AutomaticSetWatched()
+static Setting *AutomaticSetWatched(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AutomaticSetWatched");
+    CREATE_CHECKBOX_SETTING(gc, "AutomaticSetWatched", settings);
     gc->setLabel(QObject::tr("Automatically mark a recording as watched"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("If enabled, when you exit near the end of a "
@@ -1589,7 +1720,7 @@ static HostCheckBox *AutomaticSetWatched()
                     "detection is not foolproof, so do not enable this "
                     "setting if you don't want an unwatched recording marked "
                     "as watched."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostSpinBox *LiveTVIdleTimeout()
@@ -1779,9 +1910,9 @@ static HostComboBox *XineramaMonitorAspectRatio()
     return gc;
 }
 
-static HostComboBox *LetterboxingColour()
+static Setting *LetterboxingColour(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("LetterboxColour");
+    CREATE_COMBOBOX_SETTING(gc, "LetterboxColour", settings);
     gc->setLabel(QObject::tr("Letterboxing color"));
     for (int m = kLetterBoxColour_Black; m < kLetterBoxColour_END; ++m)
         gc->addSelection(toString((LetterBoxColour)m), QString::number(m));
@@ -1791,12 +1922,12 @@ static HostComboBox *LetterboxingColour()
             "letterboxing, but those with plasma screens may prefer gray "
             "to minimize burn-in.") + " " +
         QObject::tr("Currently only works with XVideo video renderer."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *AspectOverride()
+static Setting *AspectOverride(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("AspectOverride");
+    CREATE_COMBOBOX_SETTING(gc, "AspectOverride", settings);
     gc->setLabel(QObject::tr("Video aspect override"));
     for (int m = kAspect_Off; m < kAspect_END; ++m)
         gc->addSelection(toString((AspectOverrideMode)m), QString::number(m));
@@ -1804,12 +1935,12 @@ static HostComboBox *AspectOverride()
                         "When enabled, these will override the aspect "
                         "ratio specified by any broadcaster for all "
                         "video streams."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *AdjustFill()
+static Setting *AdjustFill(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("AdjustFill");
+    CREATE_COMBOBOX_SETTING(gc, "AdjustFill", settings);
     gc->setLabel(QObject::tr("Zoom"));
     for (int m = kAdjustFill_Off; m < kAdjustFill_END; ++m)
         gc->addSelection(toString((AdjustFillMode)m), QString::number(m));
@@ -1820,7 +1951,7 @@ static HostComboBox *AdjustFill()
     gc->setHelpText(QObject::tr(
                         "When enabled, these will apply a predefined "
                         "zoom to all video playback in MythTV."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 // Theme settings
@@ -2711,16 +2842,16 @@ static HostLineEdit *UDPNotifyPort()
     return ge;
 }
 
-static HostCheckBox *RealtimePriority()
+static Setting *RealtimePriority(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("RealtimePriority");
+    CREATE_CHECKBOX_SETTING(gc, "RealtimePriority", settings);
     gc->setLabel(QObject::tr("Enable realtime priority threads"));
     gc->setHelpText(QObject::tr("When running mythfrontend with root "
                     "privileges, some threads can be given enhanced priority. "
                     "Disable this if mythfrontend freezes during video "
                     "playback."));
     gc->setValue(true);
-    return gc;
+    return wrap(gc, settings, false);
 }
 
 static HostCheckBox *EnableMediaMon()
@@ -3286,8 +3417,11 @@ static HostCheckBox *WatchTVGuide()
     return gc;
 }
 
-MainGeneralSettings::MainGeneralSettings()
+MainGeneralSettings::MainGeneralSettings(PlaySettings *settings,
+                                         ConfigurationWizard *base)
 {
+    if (!settings)
+    {
     DatabaseSettings::addDatabaseSettings(this);
 
     VerticalConfigurationGroup *pin =
@@ -3336,47 +3470,64 @@ MainGeneralSettings::MainGeneralSettings()
     remotecontrol->addChild(NetworkControlPort());
     remotecontrol->addChild(UDPNotifyPort());
     addChild(remotecontrol);
+    }
 }
 
-PlaybackSettings::PlaybackSettings()
+PlaybackSettings::PlaybackSettings(PlaySettings *settings,
+                                   ConfigurationWizard *base)
 {
     uint i = 0, total = 8;
 #if CONFIG_DARWIN
     total += 2;
 #endif // USING_DARWIN
+    if (settings)
+        total -= 3;
 
 
     VerticalConfigurationGroup* general1 =
         new VerticalConfigurationGroup(false);
     general1->setLabel(QObject::tr("General Playback") +
                       QString(" (%1/%2)").arg(++i).arg(total));
+    if (settings)
+        general1->setLabel(QObject::tr("Playback group settings for ") +
+                           settings->mGroupName + " - " +
+                           general1->getLabel());
 
     HorizontalConfigurationGroup *columns =
         new HorizontalConfigurationGroup(false, false, true, true);
 
     VerticalConfigurationGroup *column1 =
         new VerticalConfigurationGroup(false, false, true, true);
-    column1->addChild(RealtimePriority());
-    column1->addChild(DecodeExtraAudio());
-    column1->addChild(JumpToProgramOSD());
+    if (!settings)
+        column1->addChild(RealtimePriority(settings));
+    column1->addChild(DecodeExtraAudio(settings));
+    column1->addChild(JumpToProgramOSD(settings));
     columns->addChild(column1);
 
     VerticalConfigurationGroup *column2 =
         new VerticalConfigurationGroup(false, false, true, true);
-    column2->addChild(ClearSavedPosition());
-    column2->addChild(AltClearSavedPosition());
-    column2->addChild(AutomaticSetWatched());
-    column2->addChild(ContinueEmbeddedTVPlay());
+    column2->addChild(ClearSavedPosition(settings));
+    column2->addChild(AltClearSavedPosition(settings));
+    column2->addChild(AutomaticSetWatched(settings));
+    column2->addChild(ContinueEmbeddedTVPlay(settings));
     columns->addChild(column2);
 
     general1->addChild(columns);
-    general1->addChild(LiveTVIdleTimeout());
-    addChild(general1);
+    if (!settings)
+        general1->addChild(LiveTVIdleTimeout());
+    if (base)
+        base->addChild(general1);
+    else
+        addChild(general1);
 
     VerticalConfigurationGroup* general2 =
         new VerticalConfigurationGroup(false);
     general2->setLabel(QObject::tr("General Playback") +
                       QString(" (%1/%2)").arg(++i).arg(total));
+    if (settings)
+        general2->setLabel(QObject::tr("Playback group settings for ") +
+                           settings->mGroupName + " - " +
+                           general2->getLabel());
 
     HorizontalConfigurationGroup* oscan =
         new HorizontalConfigurationGroup(false, false, true, true);
@@ -3384,29 +3535,37 @@ PlaybackSettings::PlaybackSettings()
         new VerticalConfigurationGroup(false, false, true, true);
     VerticalConfigurationGroup *ocol2 =
         new VerticalConfigurationGroup(false, false, true, true);
-    ocol1->addChild(VertScanPercentage());
-    ocol1->addChild(YScanDisplacement());
-    ocol2->addChild(HorizScanPercentage());
-    ocol2->addChild(XScanDisplacement());
+    ocol1->addChild(VertScanPercentage(settings));
+    ocol1->addChild(YScanDisplacement(settings));
+    ocol2->addChild(HorizScanPercentage(settings));
+    ocol2->addChild(XScanDisplacement(settings));
     oscan->addChild(ocol1);
     oscan->addChild(ocol2);
 
     HorizontalConfigurationGroup* aspect_fill =
         new HorizontalConfigurationGroup(false, false, true, true);
-    aspect_fill->addChild(AspectOverride());
-    aspect_fill->addChild(AdjustFill());
+    aspect_fill->addChild(AspectOverride(settings));
+    aspect_fill->addChild(AdjustFill(settings));
 
     general2->addChild(oscan);
     general2->addChild(aspect_fill);
-    general2->addChild(LetterboxingColour());
-    general2->addChild(PIPLocationComboBox());
-    general2->addChild(PlaybackExitPrompt());
-    general2->addChild(EndOfRecordingExitPrompt());
-    addChild(general2);
+    general2->addChild(LetterboxingColour(settings));
+    general2->addChild(PIPLocationComboBox(settings));
+    general2->addChild(PlaybackExitPrompt(settings));
+    general2->addChild(EndOfRecordingExitPrompt(settings));
+    if (base)
+        base->addChild(general2);
+    else
+        addChild(general2);
 
     QString tmp = QString(" (%1/%2)").arg(++i).arg(total);
-    addChild(new PlaybackProfileConfigs(tmp));
+    if (base)
+        base->addChild(new PlaybackProfileConfigs(tmp, settings));
+    else
+        addChild(new PlaybackProfileConfigs(tmp, settings));
 
+    if (!settings)
+    {
     VerticalConfigurationGroup* pbox = new VerticalConfigurationGroup(false);
     pbox->setLabel(QObject::tr("View Recordings") +
                    QString(" (%1/%2)").arg(++i).arg(total));
@@ -3433,38 +3592,72 @@ PlaybackSettings::PlaybackSettings()
     pbox3->addChild(DisplayGroupTitleSort());
     pbox3->addChild(new WatchListSettings());
     addChild(pbox3);
+    }
 
     VerticalConfigurationGroup* seek = new VerticalConfigurationGroup(false);
     seek->setLabel(QObject::tr("Seeking") +
                    QString(" (%1/%2)").arg(++i).arg(total));
-    seek->addChild(SmartForward());
-    seek->addChild(FFRewReposTime());
-    seek->addChild(FFRewReverse());
-    seek->addChild(ExactSeeking());
-    addChild(seek);
+    if (settings)
+        seek->setLabel(QObject::tr("Playback group settings for ") +
+                       settings->mGroupName + " - " +
+                       seek->getLabel());
+    seek->addChild(SmartForward(settings));
+    seek->addChild(FFRewReposTime(settings));
+    seek->addChild(FFRewReverse(settings));
+    seek->addChild(ExactSeeking(settings));
+    if (base)
+        base->addChild(seek);
+    else
+        addChild(seek);
 
     VerticalConfigurationGroup* comms = new VerticalConfigurationGroup(false);
     comms->setLabel(QObject::tr("Commercial Skip") +
                     QString(" (%1/%2)").arg(++i).arg(total));
-    comms->addChild(AutoCommercialSkip());
-    comms->addChild(CommRewindAmount());
-    comms->addChild(CommNotifyAmount());
+    if (settings)
+        comms->setLabel(QObject::tr("Playback group settings for ") +
+                        settings->mGroupName + " - " +
+                        comms->getLabel());
+    comms->addChild(AutoCommercialSkip(settings));
+    comms->addChild(CommRewindAmount(settings));
+    comms->addChild(CommNotifyAmount(settings));
+    if (!settings) // these are global settings, not host-specific
+    {
     comms->addChild(MaximumCommercialSkip());
     comms->addChild(MergeShortCommBreaks());
-    addChild(comms);
+    }
+    if (base)
+        base->addChild(comms);
+    else
+        addChild(comms);
 
 #if CONFIG_DARWIN
     VerticalConfigurationGroup* mac1 = new VerticalConfigurationGroup(false);
     mac1->setLabel(QObject::tr("Mac OS X Video Settings") +
                    QString(" (%1/%2)").arg(++i).arg(total));
+    if (settings)
+        mac1->setLabel(QObject::tr("Playback group settings for ") +
+                       settings->mGroupName + " - " +
+                       mac1->getLabel());
+    if (!settings)
+    {
     mac1->addChild(MacGammaCorrect());
     mac1->addChild(MacScaleUp());
     mac1->addChild(MacFullSkip());
-    addChild(mac1);
+    }
+    if (base)
+        base->addChild(mac1);
+    else
+        addChild(mac1);
 
     VerticalConfigurationGroup* mac2 = new VerticalConfigurationGroup(false);
     mac2->setLabel(QObject::tr("Mac OS X Video Settings") +
                    QString(" (%1/%2)").arg(++i).arg(total));
+    if (settings)
+        mac2->setLabel(QObject::tr("Playback group settings for ") +
+                       settings->mGroupName + " - " +
+                       mac2->getLabel());
+    if (!setings)
+    {
     mac2->addChild(new MacMainSettings());
     mac2->addChild(new MacFloatSettings());
 
@@ -3478,21 +3671,33 @@ PlaybackSettings::PlaybackSettings()
 #endif
 }
 
-OSDSettings::OSDSettings()
+OSDSettings::OSDSettings(PlaySettings *settings,
+                         ConfigurationWizard *base)
 {
     VerticalConfigurationGroup* osd = new VerticalConfigurationGroup(false);
     osd->setLabel(QObject::tr("On-screen Display"));
+    if (settings)
+        osd->setLabel(QObject::tr("Playback group settings for ") +
+                      settings->mGroupName + " - " +
+                      osd->getLabel());
 
-    osd->addChild(EnableMHEG());
-    osd->addChild(PersistentBrowseMode());
-    osd->addChild(BrowseAllTuners());
-    osd->addChild(CCBackground());
-    osd->addChild(DefaultCCMode());
-    osd->addChild(PreferCC708());
+    if (!settings)
+    {
+    osd->addChild(EnableMHEG(settings));
+    osd->addChild(PersistentBrowseMode(settings));
+    osd->addChild(BrowseAllTuners(settings));
+    }
+    osd->addChild(CCBackground(settings));
+    osd->addChild(DefaultCCMode(settings));
+    osd->addChild(PreferCC708(settings));
+    if (!settings)
     osd->addChild(SubtitleFont());
-    osd->addChild(OSDCC708TextZoomPercentage());
-    osd->addChild(SubtitleCodec());
-    addChild(osd);
+    osd->addChild(OSDCC708TextZoomPercentage(settings));
+    osd->addChild(SubtitleCodec(settings));
+    if (base)
+        base->addChild(osd);
+    else
+        addChild(osd);
 
     //VerticalConfigurationGroup *cc = new VerticalConfigurationGroup(false);
     //cc->setLabel(QObject::tr("Closed Captions"));
diff --git a/mythtv/programs/mythfrontend/globalsettings.h b/mythtv/programs/mythfrontend/globalsettings.h
index 90cb98a..032d476 100644
--- a/mythtv/programs/mythfrontend/globalsettings.h
+++ b/mythtv/programs/mythfrontend/globalsettings.h
@@ -11,6 +11,7 @@
 #include <QMutex>
 
 class QFileInfo;
+class PlaySettings;
 
 class ThemeSelector : public HostImageSelect
 {
@@ -24,13 +25,15 @@ class ThemeSelector : public HostImageSelect
 class PlaybackSettings : public ConfigurationWizard
 {
   public:
-    PlaybackSettings();
+    PlaybackSettings(PlaySettings *settings=NULL,
+                     ConfigurationWizard *base=NULL);
 };
 
 class OSDSettings: virtual public ConfigurationWizard
 {
   public:
-    OSDSettings();
+    OSDSettings(PlaySettings *settings=NULL,
+                ConfigurationWizard *base=NULL);
 };
 
 class GeneralSettings : public ConfigurationWizard
@@ -54,7 +57,8 @@ class AppearanceSettings : public ConfigurationWizard
 class MainGeneralSettings : public ConfigurationWizard
 {
   public:
-    MainGeneralSettings();
+    MainGeneralSettings(PlaySettings *settings=NULL,
+                        ConfigurationWizard *base=NULL);
 };
 
 class GeneralRecPrioritiesSettings : public ConfigurationWizard
@@ -142,7 +146,7 @@ class PlaybackProfileConfigs : public TriggeredConfigurationGroup
     Q_OBJECT
 
   public:
-    PlaybackProfileConfigs(const QString &str);
+    PlaybackProfileConfigs(const QString &str, PlaySettings *settings);
     virtual ~PlaybackProfileConfigs();
 
   private:
@@ -154,7 +158,7 @@ class PlaybackProfileConfigs : public TriggeredConfigurationGroup
 
   private:
     QStringList   profiles;
-    HostComboBox *grouptrigger;
+    ComboBoxSetting *grouptrigger;
 };
 
 #endif
diff --git a/mythtv/programs/mythfrontend/main.cpp b/mythtv/programs/mythfrontend/main.cpp
index 95a4521..814fb5e 100644
--- a/mythtv/programs/mythfrontend/main.cpp
+++ b/mythtv/programs/mythfrontend/main.cpp
@@ -38,6 +38,7 @@ using namespace std;
 #include "grabbersettings.h"
 #include "profilegroup.h"
 #include "playgroup.h"
+#include "playsettings.h"
 #include "networkcontrol.h"
 #include "dvdringbuffer.h"
 #include "scheduledrecording.h"
@@ -566,6 +567,27 @@ static void showStatus(void)
         delete statusbox;
 }
 
+ConfigurationWizard *createPlaybackSettingsForPlaybackGroup(PlaySettings *settings, ConfigurationWizard *base)
+{
+    return new PlaybackSettings(settings, base);
+}
+
+ConfigurationWizard *createOSDSettingsForPlaybackGroup(PlaySettings *settings, ConfigurationWizard *base)
+{
+    return new OSDSettings(settings, base);
+}
+
+ConfigurationWizard *createMainGeneralSettingsForPlaybackGroup(PlaySettings *settings, ConfigurationWizard *base)
+{
+    return new MainGeneralSettings(settings, base);
+}
+
+static PlayGroupEditor::SettingsLookup pbgroupSetup[] = {
+    createPlaybackSettingsForPlaybackGroup,
+    createOSDSettingsForPlaybackGroup,
+    createMainGeneralSettingsForPlaybackGroup
+};
+
 static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump = false)
 {
     QString message = QObject::tr("Loading videos ...");
@@ -879,7 +901,8 @@ static void TVMenuCallback(void *data, QString &selection)
     }
     else if (sel == "settings playgroup")
     {
-        PlayGroupEditor editor;
+        PlayGroupEditor editor(pbgroupSetup,
+                               sizeof(pbgroupSetup)/sizeof(*pbgroupSetup));
         editor.exec();
     }
     else if (sel == "settings general")
@@ -1124,6 +1147,7 @@ static int internal_play_media(const QString &mrl, const QString &plot,
                     pos = (int64_t)((*++it).toLongLong() & 0xffffffffLL);
                 }
             }
+            pginfo->SetPlaybackGroup("Videos");
         }
         else
         {
@@ -1135,7 +1159,10 @@ static int internal_play_media(const QString &mrl, const QString &plot,
         delete dvd;
     }
     else if (pginfo->IsVideo())
+    {
         pos = pginfo->QueryBookmark();
+        pginfo->SetPlaybackGroup("Videos");
+    }
 
     if (pos > 0)
     {
diff --git a/mythtv/programs/mythfrontend/setupwizard_video.cpp b/mythtv/programs/mythfrontend/setupwizard_video.cpp
index 52ed4d5..8e55225 100644
--- a/mythtv/programs/mythfrontend/setupwizard_video.cpp
+++ b/mythtv/programs/mythfrontend/setupwizard_video.cpp
@@ -33,7 +33,7 @@ VideoSetupWizard::VideoSetupWizard(MythScreenStack *parent, MythScreenType *gene
       m_prevButton(NULL)
 {
     m_popupStack = GetMythMainWindow()->GetStack("popup stack");
-    m_vdp = new VideoDisplayProfile();
+    m_vdp = new VideoDisplayProfile(NULL);
     m_audioScreen->Hide();
     gCoreContext->addListener(this);
 }
@@ -110,7 +110,7 @@ void VideoSetupWizard::loadData(void)
         item->SetData(*i);
     }
 
-    QString currentpbp = m_vdp->GetDefaultProfileName(gCoreContext->GetHostName());
+    QString currentpbp = m_vdp->GetDefaultProfileName(gCoreContext->GetHostName(), NULL);
     if (!currentpbp.isEmpty())
     {
         MythUIButtonListItem *set =
@@ -211,7 +211,7 @@ void VideoSetupWizard::playVideoTest(QString desc, QString title, QString file)
 {
     QString desiredpbp =
         m_playbackProfileButtonList->GetItemCurrent()->GetText();
-    QString currentpbp = m_vdp->GetDefaultProfileName(gCoreContext->GetHostName());
+    QString currentpbp = m_vdp->GetDefaultProfileName(gCoreContext->GetHostName(), NULL);
 
     m_vdp->SetDefaultProfileName(desiredpbp, gCoreContext->GetHostName());
     GetMythMainWindow()->HandleMedia("Internal", file, desc, title);
