Index: libs/libmythtv/videoout_vdpau.h
===================================================================
--- libs/libmythtv/videoout_vdpau.h	(revision 24189)
+++ libs/libmythtv/videoout_vdpau.h	(working copy)
@@ -16,7 +16,7 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts);
-    VideoOutputVDPAU(MythCodecID codec_id);
+    VideoOutputVDPAU(PlaySettings *settings, MythCodecID codec_id);
     ~VideoOutputVDPAU();
     bool Init(int width, int height, float aspect, WId winid,
               int winx, int winy, int winw, int winh, WId embedid = 0);
@@ -49,7 +49,8 @@
                                     const QSize &video_dim);
     static MythCodecID GetBestSupportedCodec(uint width, uint height,
                                              uint stream_type,
-                                             bool no_acceleration);
+                                             bool no_acceleration,
+                                             PlaySettings *settings);
     DisplayInfo  GetDisplayInfo(void);
     virtual bool IsPIPSupported(void) const { return true; }
     virtual bool IsPBPSupported(void) const { return false; }
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 24189)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -59,6 +59,7 @@
 #include "util-osx-cocoa.h"
 #include "mythverbose.h"
 #include "myth_imgconvert.h"
+#include "playsettings.h"
 
 extern "C" {
 #include "vbitext/vbi.h"
@@ -224,20 +225,6 @@
       // Debugging variables
       output_jmeter(NULL)
 {
-
-    // Playback (output) zoom control
-    detect_letter_box = new DetectLetterbox(this);
-
-    vbimode = VBIMode::Parse(gContext->GetSetting("VbiFormat"));
-
-    commrewindamount = gContext->GetNumSetting("CommRewindAmount",0);
-    commnotifyamount = gContext->GetNumSetting("CommNotifyAmount",0);
-    decode_extra_audio=gContext->GetNumSetting("DecodeExtraAudio", 0);
-    itvEnabled       = gContext->GetNumSetting("EnableMHEG", 0);
-    db_prefer708     = gContext->GetNumSetting("Prefer708Captions", 1);
-    autocommercialskip = (CommSkipMode)
-        gContext->GetNumSetting("AutoCommercialSkip", kCommSkipOff);
-
     lastIgnoredManualSkip = QDateTime::currentDateTime().addSecs(-10);
 
     bzero(&txtbuffers, sizeof(txtbuffers));
@@ -669,7 +656,7 @@
 
     if (using_null_videoout)
     {
-        videoOutput = new VideoOutputNull();
+        videoOutput = new VideoOutputNull(GetPlaySettings());
         if (!videoOutput->Init(video_disp_dim.width(), video_disp_dim.height(),
                                video_aspect, 0, 0, 0, 0, 0, 0))
         {
@@ -717,7 +704,7 @@
             pipState,
             video_disp_dim, video_aspect,
             widget->winId(), display_rect, (video_frame_rate * play_speed),
-            0 /*embedid*/);
+            0 /*embedid*/, GetPlaySettings());
 
         if (!videoOutput)
         {
@@ -739,7 +726,8 @@
         videoOutput->EmbedInWidget(embx, emby, embw, embh);
     }
 
-    SetCaptionsEnabled(gContext->GetNumSetting("DefaultCCMode"), false);
+    SetCaptionsEnabled(GetPlaySettings()->GetNumSetting("DefaultCCMode", 0),
+                       false);
 
     InitFilters();
 
@@ -790,7 +778,7 @@
 
 void NuppelVideoPlayer::ReinitVideo(void)
 {
-    if (!videoOutput->IsPreferredRenderer(video_disp_dim))
+    if (!videoOutput->IsPreferredRenderer(video_disp_dim, GetPlaySettings()))
     {
         VERBOSE(VB_PLAYBACK, LOC + QString("Need to switch video renderer."));
         SetErrored(QObject::tr("Need to switch video renderer."));
@@ -858,13 +846,15 @@
 
     if (!audioOutput && !using_null_videoout && player_ctx->IsAudioNeeded())
     {
-        bool setVolume = gContext->GetNumSetting("MythControlsVolume", 1);
+        bool setVolume =
+            GetPlaySettings()->GetNumSetting("MythControlsVolume", 1);
         audioOutput = AudioOutput::OpenAudio(audio_main_device,
                                              audio_passthru_device,
                                              audio_bits, audio_channels,
                                              audio_codec, audio_samplerate,
                                              AUDIOOUTPUT_VIDEO,
-                                             setVolume, audio_passthru);
+                                             setVolume, audio_passthru,
+                                             GetPlaySettings());
         if (!audioOutput)
             errMsg = QObject::tr("Unable to create AudioOutput.");
         else
@@ -896,7 +886,8 @@
     if (audioOutput)
     {
         const AudioSettings settings(audio_bits, audio_channels, audio_codec,
-                                     audio_samplerate, audio_passthru);
+                                     audio_samplerate, audio_passthru,
+                                     GetPlaySettings());
         audioOutput->Reconfigure(settings);
         if (audio_passthru)
             audio_channels = 2;
@@ -2908,7 +2899,8 @@
         m_double_process = videoOutput->IsExtraProcessingRequired();
 
         videosync = VideoSync::BestMethod(
-            videoOutput, fr_int, rf_int, m_double_framerate);
+            videoOutput, GetPlaySettings(),
+            fr_int, rf_int, m_double_framerate);
 
         // Make sure video sync can do it
         if (videosync != NULL && m_double_framerate)
@@ -3390,7 +3382,7 @@
         QRect visible, total;
         float aspect, scaling;
 
-        osd = new OSD();
+        osd = new OSD(GetPlaySettings());
 
         osd->SetListener(m_tv);
 
@@ -3469,7 +3461,7 @@
 
         GetDecoder()->setExactSeeks(seeks);
 
-        if (gContext->GetNumSetting("ClearSavedPosition", 1) &&
+        if (GetPlaySettings()->GetNumSetting("ClearSavedPosition", 1) &&
             !player_ctx->IsPIP())
         {
             if (player_ctx->buffer->isDVD())
@@ -3737,7 +3729,7 @@
             ++deleteIter;
             if (deleteIter.key() == totalFrames)
             {
-                if (!(gContext->GetNumSetting("EndOfRecordingExitPrompt") == 1
+                if (!(GetPlaySettings()->GetNumSetting("EndOfRecordingExitPrompt", 0) == 1
                       && !player_ctx->IsPIP() &&
                       player_ctx->GetState() == kState_WatchingPreRecorded))
                 {
@@ -3911,7 +3903,8 @@
 
     if (sim_pip_players.isEmpty())
     {
-        return (PIPLocation)gContext->GetNumSetting("PIPLocation", kPIPTopLeft);
+        return (PIPLocation)GetPlaySettings()->GetNumSetting("PIPLocation",
+                                                             kPIPTopLeft);
     }
 
     // order of preference, could be stored in db if we want it configurable
@@ -4699,6 +4692,22 @@
     exactseeks   = frame_exact_seek;
     player_ctx   = ctx;
     livetv       = ctx->tvchain;
+
+    vbimode = VBIMode::Parse(GetPlaySettings()->GetSetting("VbiFormat", ""));
+
+    // Playback (output) zoom control
+    detect_letter_box = new DetectLetterbox(this);
+
+    commrewindamount = GetPlaySettings()->GetNumSetting("CommRewindAmount", 0);
+    commnotifyamount = GetPlaySettings()->GetNumSetting("CommNotifyAmount", 0);
+    decode_extra_audio = GetPlaySettings()->GetNumSetting("DecodeExtraAudio", 0);
+    itvEnabled = GetPlaySettings()->GetNumSetting("EnableMHEG", 0);
+    db_prefer708 = GetPlaySettings()->GetNumSetting("Prefer708Captions", 1);
+    autocommercialskip = (CommSkipMode)
+        GetPlaySettings()->GetNumSetting("AutoCommercialSkip", kCommSkipOff);
+    SetAudioInfo(GetPlaySettings()->GetSetting("AudioOutputDevice", ""),
+                 GetPlaySettings()->GetSetting("PassThruOutputDevice", ""),
+                 gContext->GetNumSetting("AudioSampleRate", 44100));
 }
 
 void NuppelVideoPlayer::SetDeleteIter(void)
@@ -7377,7 +7386,8 @@
 {
     QMutexLocker locker(&subtitleLock);
     textSubtitles.Clear();
-    return TextSubtitleParser::LoadSubtitles(subtitleFileName, textSubtitles);
+    return TextSubtitleParser::LoadSubtitles(subtitleFileName, textSubtitles,
+                                             GetPlaySettings());
 }
 
 void NuppelVideoPlayer::ChangeDVDTrack(bool ffw)
Index: libs/libmythtv/videooutwindow.cpp
===================================================================
--- libs/libmythtv/videooutwindow.cpp	(revision 24189)
+++ libs/libmythtv/videooutwindow.cpp	(working copy)
@@ -30,6 +30,7 @@
 #include "videooutwindow.h"
 #include "osd.h"
 #include "osdsurface.h"
+#include "playsettings.h"
 #include "NuppelVideoPlayer.h"
 #include "videodisplayprofile.h"
 #include "decoderbase.h"
@@ -54,7 +55,7 @@
 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 @@
 
     // Various state variables
     embedding(false), needrepaint(false),
-    allowpreviewepg(true), pip_state(kPIPOff)
+    allowpreviewepg(true), pip_state(kPIPOff),
+
+    settings(_settings)
 {
     db_pip_size = gContext->GetNumSetting("PIPSize", 26);
 
-    db_move = QPoint(gContext->GetNumSetting("xScanDisplacement", 0),
-                     gContext->GetNumSetting("yScanDisplacement", 0));
+    db_move = QPoint(settings->GetNumSetting("xScanDisplacement", 0),
+                     settings->GetNumSetting("yScanDisplacement", 0));
     db_use_gui_size = gContext->GetNumSetting("GuiSizeForTV", 0);
 
     QDesktopWidget *desktop = NULL;
@@ -613,9 +616,9 @@
     if (change)
     {
         db_scale_vert =
-            gContext->GetNumSetting("VertScanPercentage", 0) * 0.01f;
+            settings->GetNumSetting("VertScanPercentage", 0) * 0.01f;
         db_scale_horiz =
-            gContext->GetNumSetting("HorizScanPercentage", 0) * 0.01f;
+            settings->GetNumSetting("HorizScanPercentage", 0) * 0.01f;
         db_scaling_allowed = true;
     }
     else
Index: libs/libmythtv/videoout_d3d.cpp
===================================================================
--- libs/libmythtv/videoout_d3d.cpp	(revision 24189)
+++ libs/libmythtv/videoout_d3d.cpp	(working copy)
@@ -948,8 +948,8 @@
     opts.priorities->insert("direct3d", 55);
 }
 
-VideoOutputD3D::VideoOutputD3D(void)
-  : VideoOutput(),         m_lock(QMutex::Recursive),
+VideoOutputD3D::VideoOutputD3D(PlaySettings *settings)
+  : VideoOutput(settings),         m_lock(QMutex::Recursive),
     m_hWnd(NULL),          m_ctx(NULL),
     m_video(NULL),         m_osd(NULL),
     m_d3d_osd(false),      m_osd_ready(false),
Index: libs/libmythtv/DetectLetterbox.cpp
===================================================================
--- libs/libmythtv/DetectLetterbox.cpp	(revision 24189)
+++ libs/libmythtv/DetectLetterbox.cpp	(working copy)
@@ -5,10 +5,11 @@
 #include "NuppelVideoPlayer.h"
 #include "videoouttypes.h"
 #include "mythcontext.h"
+#include "playsettings.h"
 
 DetectLetterbox::DetectLetterbox(NuppelVideoPlayer* const nvp)
 {
-    int dbAdjustFill = gContext->GetNumSetting("AdjustFill", 0);
+    int dbAdjustFill = nvp->GetPlaySettings()->GetNumSetting("AdjustFill", 0);
     isDetectLetterbox = dbAdjustFill >= kAdjustFill_AutoDetect_DefaultOff;
     firstFrameChecked = 0;
     detectLetterboxDefaultMode = (AdjustFillMode) max((int) kAdjustFill_Off,
@@ -17,7 +18,8 @@
     detectLetterboxPossibleHalfFrame = -1;
     detectLetterboxPossibleFullFrame = -1;
     detectLetterboxDetectedMode = nvp->GetAdjustFill();
-    detectLetterboxLimit = gContext->GetNumSetting("DetectLeterboxLimit", 75);
+    detectLetterboxLimit =
+        nvp->GetPlaySettings()->GetNumSetting("DetectLeterboxLimit", 75);
     nupple_video_player = nvp;
 }
 
Index: libs/libmythtv/videoout_opengl.cpp
===================================================================
--- libs/libmythtv/videoout_opengl.cpp	(revision 24189)
+++ libs/libmythtv/videoout_opengl.cpp	(working copy)
@@ -38,8 +38,8 @@
     opts.priorities->insert("opengl", 65);
 }
 
-VideoOutputOpenGL::VideoOutputOpenGL(void)
-    : VideoOutput(),
+VideoOutputOpenGL::VideoOutputOpenGL(PlaySettings *settings)
+    : VideoOutput(settings),
     gl_context_lock(QMutex::Recursive),
     gl_context(NULL), gl_videochain(NULL),
     gl_osdchain(NULL), gl_pipchain_active(NULL),
Index: libs/libmythtv/videoout_quartz.cpp
===================================================================
--- libs/libmythtv/videoout_quartz.cpp	(revision 24189)
+++ libs/libmythtv/videoout_quartz.cpp	(working copy)
@@ -65,6 +65,8 @@
 #include "videodisplayprofile.h"
 #include "videoout_dvdv.h"
 
+class PlaySettings;
+
 #define LOC     QString("VideoOutputQuartz::")
 #define LOC_ERR QString("VideoOutputQuartz Error: ")
 
@@ -1108,9 +1110,9 @@
 /** \class VideoOutputQuartz
  *  \brief Implementation of Quartz (Mac OS X windowing system) video output
  */
-VideoOutputQuartz::VideoOutputQuartz(
+VideoOutputQuartz::VideoOutputQuartz(PlaySettings *settings
     MythCodecID _myth_codec_id, void *codec_priv) :
-    VideoOutput(), Started(false), data(new QuartzData()),
+    VideoOutput(settings), Started(false), data(new QuartzData()),
     myth_codec_id(_myth_codec_id)
 {
     init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
@@ -1815,12 +1817,12 @@
 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 == "libmpeg2") || (dec == "ffmpeg"))
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 24189)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include "DVDRingBuffer.h"
 #include "videodisplayprofile.h"
 #include "mythuihelper.h"
+#include "playsettings.h"
 
 #include "lcddevice.h"
 
@@ -517,17 +518,23 @@
     av_log_set_level((debug) ? AV_LOG_DEBUG : AV_LOG_ERROR);
     av_log_set_callback(myth_av_log);
 
-    max_channels = (uint) gContext->GetNumSetting("MaxChannels", 2);
-    allow_ac3_passthru = (max_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false;
-    allow_dts_passthru = (max_channels > 2) ? gContext->GetNumSetting("DTSPassThru", false) : false;
-    internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
+    max_channels =
+        (uint) GetNVP()->GetPlaySettings()->GetNumSetting("MaxChannels", 2);
+    allow_ac3_passthru = (max_channels > 2) ?
+        GetNVP()->GetPlaySettings()->GetNumSetting("AC3PassThru", false) :
+        false;
+    allow_dts_passthru = (max_channels > 2) ?
+        GetNVP()->GetPlaySettings()->GetNumSetting("DTSPassThru", false) :
+        false;
+    internal_vol =
+        GetNVP()->GetPlaySettings()->GetNumSetting("MythControlsVolume", 0);
 
     audioIn.sample_size = -32; // force SetupAudioStream to run once
     itv = GetNVP()->GetInteractiveTV();
 
     cc608_build_parity_table(cc608_parity_table);
 
-    if (gContext->GetNumSetting("CCBackground", 0))
+    if (GetNVP()->GetPlaySettings()->GetNumSetting("CCBackground", 0))
         CC708Window::forceWhiteOnBlackText = true;
 
     no_dts_hack = false;
@@ -1425,7 +1432,7 @@
         codec = find_vdpau_decoder(codec, enc->codec_id);
 
     if (selectedStream &&
-        !gContext->GetNumSetting("DecodeExtraAudio", 0) &&
+        !GetNVP()->GetPlaySettings()->GetNumSetting("DecodeExtraAudio", 0) &&
         !CODEC_IS_HWACCEL(codec))
     {
         SetLowBuffers(false);
@@ -1907,7 +1914,7 @@
 
                 if (!is_db_ignored)
                 {
-                    VideoDisplayProfile vdp;
+                    VideoDisplayProfile vdp(GetNVP()->GetPlaySettings());
                     vdp.SetInput(QSize(width, height));
                     dec = vdp.GetDecoder();
                     thread_count = vdp.GetMaxCPUs();
@@ -1935,7 +1942,8 @@
                     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,
+                        GetNVP()->GetPlaySettings());
 
                     if (vdpau_mcid >= video_codec_id)
                     {
@@ -1967,7 +1975,8 @@
                         /* mpeg type    */ mpeg_version(enc->codec_id),
                         /* xvmc pix fmt */ xvmc_pixel_format(enc->pix_fmt),
                         /* test surface */ codec_is_std(video_codec_id),
-                        /* force_xv     */ force_xv);
+                        /* force_xv     */ force_xv,
+                        GetNVP()->GetPlaySettings());
 
                     if (mcid >= video_codec_id)
                     {
@@ -2000,7 +2009,8 @@
                         /* osd dim      */ 0, 0,
                         /* mpeg type    */ mpeg_version(enc->codec_id),
                         /* pixel format */
-                        (PIX_FMT_YUV420P == enc->pix_fmt) ? FOURCC_I420 : 0);
+                        (PIX_FMT_YUV420P == enc->pix_fmt) ? FOURCC_I420 : 0,
+                        GetNVP()->GetPlaySettings());
 
                     if (quartz_mcid >= video_codec_id)
                     {
Index: libs/libmythtv/osdtypes.cpp
===================================================================
--- libs/libmythtv/osdtypes.cpp	(revision 24189)
+++ libs/libmythtv/osdtypes.cpp	(working copy)
@@ -18,6 +18,7 @@
 #include "mythcontext.h"
 #include "mythdialogs.h"
 #include "mythverbose.h"
+#include "playsettings.h"
 
 #ifdef USING_FRIBIDI
     #include "fribidi/fribidi.h"
@@ -2359,7 +2360,8 @@
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 OSDTypeCC::OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
-                     int dispw, int disph, float wmult, float hmult)
+                     int dispw, int disph, float wmult, float hmult,
+                     PlaySettings *settings)
          : OSDType(name)
 {
     m_font = font;
@@ -2373,7 +2375,7 @@
 
     QRect rect = QRect(0, 0, 0, 0);
     m_box = new OSDTypeBox("cc_background", rect, wmult, hmult);
-    m_ccbackground = gContext->GetNumSetting("CCBackground", 0);
+    m_ccbackground = settings->GetNumSetting("CCBackground", 0);
 }
 
 OSDTypeCC::~OSDTypeCC()
Index: libs/libmythtv/playgroup.cpp
===================================================================
--- libs/libmythtv/playgroup.cpp	(revision 24189)
+++ libs/libmythtv/playgroup.cpp	(working copy)
@@ -2,6 +2,7 @@
 #include "mythdb.h"
 #include "playgroup.h"
 #include "programinfo.h"
+#include "playsettings.h"
 
 // A parameter associated with the profile itself
 class PlayGroupDBStorage : public SimpleDBStorage
@@ -211,8 +212,9 @@
     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);
@@ -243,6 +245,9 @@
     }
 
     PlayGroup 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
@@ -277,6 +282,7 @@
         query.bindValue(":NAME", name);
         if (!query.exec())
             MythDB::DBError("PlayGroupEditor::doDelete", query);
+        PlaySettings::deleteGroup(name);
 
         int lastIndex = listbox->getValueIndex(name);
         lastValue = "";
Index: libs/libmythtv/videoout_opengl.h
===================================================================
--- libs/libmythtv/videoout_opengl.h	(revision 24189)
+++ libs/libmythtv/videoout_opengl.h	(working copy)
@@ -10,7 +10,7 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputOpenGL();
+    VideoOutputOpenGL(PlaySettings *settings);
    ~VideoOutputOpenGL();
 
     bool Init(int width, int height, float aspect, WId winid,
Index: libs/libmythtv/osdtypes.h
===================================================================
--- libs/libmythtv/osdtypes.h	(revision 24189)
+++ libs/libmythtv/osdtypes.h	(working copy)
@@ -31,6 +31,7 @@
 class OSDTypeText;
 class OSDSurface;
 class TV;
+class PlaySettings;
 
 typedef QHash<QString,QString> InfoMap;
 typedef QMap<int,uint>         HotKeyMap;
@@ -573,7 +574,8 @@
 {
   public:
     OSDTypeCC(const QString &name, TTFFont *font, int xoff, int yoff,
-              int dispw, int disph, float wmult, float hmult);
+              int dispw, int disph, float wmult, float hmult,
+              PlaySettings *settings);
    ~OSDTypeCC();
 
     void Reinit(float wmult, float hmult);
Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 24189)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -56,6 +56,7 @@
 class TV;
 class OSDListTreeItemEnteredEvent;
 class OSDListTreeItemSelectedEvent;
+class PlaySettings;
 
 typedef QMap<QString,InfoMap>    DDValueMap;
 typedef QMap<QString,DDValueMap> DDKeyMap;
@@ -179,7 +180,7 @@
         unsigned long seconds;
     };
 
-    TV(void);
+    TV(PlaySettings *settings);
    ~TV();
 
     bool Init(bool createWindow = true);
@@ -204,7 +205,7 @@
 
     // 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;
@@ -593,7 +594,7 @@
     static TVState RemoveRecording(TVState state);
     void RestoreScreenSaver(const PlayerContext*);
 
-    void InitUDPNotifyEvent(void);
+    void InitUDPNotifyEvent(PlaySettings *settings);
 
     /// true if dialog is either videoplayexit, playexit or askdelete dialog
     bool IsVideoExitDialog(const QString &dialog_name);
Index: libs/libmythtv/playgroup.h
===================================================================
--- libs/libmythtv/playgroup.h	(revision 24189)
+++ libs/libmythtv/playgroup.h	(working copy)
@@ -7,6 +7,7 @@
 #include "mythwidgets.h"
 
 class ProgramInfo;
+class PlaySettings;
 
 class MPUBLIC PlayGroup: public ConfigurationWizard
 {
@@ -29,7 +30,9 @@
     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) { }
@@ -44,6 +47,8 @@
   protected:
     ListBoxSetting *listbox;
     QString         lastValue;
+    SettingsLookup *getSettings;
+    int             getSettingsSize;
 };
 
 #endif
Index: libs/libmythtv/dbcheck.cpp
===================================================================
--- libs/libmythtv/dbcheck.cpp	(revision 24189)
+++ libs/libmythtv/dbcheck.cpp	(working copy)
@@ -3569,7 +3569,8 @@
 
             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--"))
@@ -5637,6 +5638,13 @@
 "  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',"
Index: libs/libmythtv/videoout_vdpau.cpp
===================================================================
--- libs/libmythtv/videoout_vdpau.cpp	(revision 24189)
+++ libs/libmythtv/videoout_vdpau.cpp	(working copy)
@@ -46,8 +46,8 @@
     opts.deints->insert("vdpau", deints);
 }
 
-VideoOutputVDPAU::VideoOutputVDPAU(MythCodecID codec_id)
-  : VideoOutput(),
+VideoOutputVDPAU::VideoOutputVDPAU(PlaySettings *settings, MythCodecID codec_id)
+  : VideoOutput(settings),
     m_codec_id(codec_id),    m_win(0),         m_render(NULL),
     m_buffer_size(NUM_VDPAU_BUFFERS),          m_pause_surface(0),
     m_need_deintrefs(false), m_video_mixer(0), m_mixer_features(kVDPFeatNone),
@@ -858,10 +858,10 @@
 
 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();
 
Index: libs/libmythtv/videoout_directfb.cpp
===================================================================
--- libs/libmythtv/videoout_directfb.cpp	(revision 24189)
+++ libs/libmythtv/videoout_directfb.cpp	(working copy)
@@ -274,8 +274,8 @@
     opts.priorities->insert("directfb", 60);
 }
 
-VideoOutputDirectfb::VideoOutputDirectfb(void)
-    : VideoOutput(), XJ_started(false), widget(NULL),
+VideoOutputDirectfb::VideoOutputDirectfb(PlaySettings *settings)
+    : VideoOutput(settings), XJ_started(false), widget(NULL),
       data(new DirectfbData())
 {
     init(&pauseFrame, FMT_YV12, NULL, 0, 0, 0, 0);
Index: libs/libmythtv/videoout_d3d.h
===================================================================
--- libs/libmythtv/videoout_d3d.h	(revision 24189)
+++ libs/libmythtv/videoout_d3d.h	(working copy)
@@ -93,7 +93,7 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputD3D();
+    VideoOutputD3D(PlaySettings *settings);
    ~VideoOutputD3D();
 
     bool Init(int width, int height, float aspect, WId winid,
Index: libs/libmythtv/playercontext.cpp
===================================================================
--- libs/libmythtv/playercontext.cpp	(revision 24189)
+++ libs/libmythtv/playercontext.cpp	(working copy)
@@ -14,6 +14,8 @@
 #include "videoouttypes.h"
 #include "storagegroup.h"
 #include "mythcontext.h"
+#include "DetectLetterbox.h"
+#include "playsettings.h"
 
 #define LOC QString("playCtx: ")
 #define LOC_ERR QString("playCtx, Error: ")
@@ -435,7 +437,7 @@
                               WId embedwinid, const QRect *embedbounds,
                               bool muted)
 {
-    int exact_seeking = gContext->GetNumSetting("ExactSeeking", 0);
+    int exact_seeking = settings->GetNumSetting("ExactSeeking", 0);
 
     if (HasNVP())
     {
@@ -450,9 +452,6 @@
         _nvp->DisableHardwareDecoders();
 
     _nvp->SetPlayerInfo(tv, widget, exact_seeking, this);
-    _nvp->SetAudioInfo(gContext->GetSetting("AudioOutputDevice"),
-                       gContext->GetSetting("PassThruOutputDevice"),
-                       gContext->GetNumSetting("AudioSampleRate", 44100));
     _nvp->SetAudioStretchFactor(ts_normal);
     _nvp->SetLength(playingLen);
 
@@ -888,7 +887,8 @@
 /**
  * \brief assign programinfo to the context
  */
-void PlayerContext::SetPlayingInfo(const ProgramInfo *info)
+void PlayerContext::SetPlayingInfo(const ProgramInfo *info,
+                                   PlaySettings *_settings)
 {
     bool ignoreDB = gContext->IsDatabaseIgnored();
 
@@ -900,6 +900,7 @@
             playingInfo->MarkAsInUse(false, recUsage);
         delete playingInfo;
         playingInfo = NULL;
+        // XXX delete settings?
     }
 
     if (info)
@@ -908,6 +909,8 @@
         if (!ignoreDB)
             playingInfo->MarkAsInUse(true, recUsage);
         playingLen  = playingInfo->CalculateLength();
+        settings = (_settings ? _settings :
+                    new PlaySettings(playingInfo->playgroup));
     }
 }
 
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h	(revision 24189)
+++ libs/libmythtv/NuppelVideoPlayer.h	(working copy)
@@ -196,6 +196,10 @@
     bool      GetAudioBufferStatus(uint &fill, uint &total) const;
     PIPLocation GetNextPIPLocation(void) const;
 
+    PlaySettings *GetPlaySettings(void) const {
+        return player_ctx ? player_ctx->settings : NULL;
+    }
+
     // Bool Gets
     bool    GetRawAudioState(void) const;
     bool    GetLimitKeyRepeat(void) const     { return limitKeyRepeat; }
Index: libs/libmythtv/textsubtitleparser.h
===================================================================
--- libs/libmythtv/textsubtitleparser.h	(revision 24189)
+++ libs/libmythtv/textsubtitleparser.h	(working copy)
@@ -17,6 +17,8 @@
 // Qt headers
 #include <QStringList>
 
+class PlaySettings;
+
 class text_subtitle_t
 {
   public:
@@ -75,7 +77,8 @@
 class TextSubtitleParser
 {
   public:
-    static bool LoadSubtitles(QString fileName, TextSubtitles &target);
+    static bool LoadSubtitles(QString fileName, TextSubtitles &target,
+                              PlaySettings *settings);
 };
 
 #endif
Index: libs/libmythtv/osd.h
===================================================================
--- libs/libmythtv/osd.h	(revision 24189)
+++ libs/libmythtv/osd.h	(working copy)
@@ -70,12 +70,13 @@
 class TeletextViewer;
 class QStringList;
 class QDomElement;
+class PlaySettings;
 
 class OSD : public QObject
 {
     Q_OBJECT
  public:
-    OSD();
+    OSD(PlaySettings *settings);
    ~OSD(void);
 
     void Init(const QRect &totalBounds,   int   frameRate,
@@ -233,6 +234,8 @@
 
     QObject *m_listener;
 
+    PlaySettings *settings;
+
     QRect osdBounds;
     int   frameint;
     bool  needPillarBox;
Index: libs/libmythtv/vsync.cpp
===================================================================
--- libs/libmythtv/vsync.cpp	(revision 24189)
+++ libs/libmythtv/vsync.cpp	(working copy)
@@ -34,6 +34,7 @@
 #include "mythcontext.h"
 #include "mythverbose.h"
 #include "mythmainwindow.h"
+#include "playsettings.h"
 
 #ifdef USING_XV
 #include "videoout_xv.h"
@@ -76,12 +77,13 @@
  *  \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)
 {
     VideoSync *trial = NULL;
     tryingVideoSync  = true;
-    bool tryOpenGL   = (gContext->GetNumSetting("UseOpenGLVSync", 1) &&
+    bool tryOpenGL   = (settings->GetNumSetting("UseOpenGLVSync", 1) &&
                         (getenv("NO_OPENGL_VSYNC") == NULL));
 
     // m_forceskip allows for skipping one sync method
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 24189)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -60,6 +60,7 @@
 #include "tv_play_win.h"
 #include "recordinginfo.h"
 #include "mythsystemevent.h"
+#include "playsettings.h"
 
 #if ! HAVE_ROUND
 #define round(x) ((int) ((x) + 0.5))
@@ -190,7 +191,6 @@
                  bool inPlaylist, bool initByNetworkCommand)
 {
     VERBOSE(VB_PLAYBACK, LOC + "StartTV() -- begin");
-    TV *tv = new TV();
     bool quitAll = false;
     bool showDialogs = true;
     bool playCompleted = false;
@@ -201,6 +201,9 @@
     if (tvrec)
         curProgram = new ProgramInfo(*tvrec);
 
+    PlaySettings settings(curProgram ? curProgram->playgroup : "Default");
+    TV *tv = new TV(&settings);
+
     // Initialize TV
     if (!tv->Init())
     {
@@ -232,7 +235,7 @@
         if (curProgram)
         {
             VERBOSE(VB_PLAYBACK, LOC + "tv->Playback() -- begin");
-            if (!tv->Playback(*curProgram))
+            if (!tv->Playback(*curProgram, &settings))
             {
                 quitAll = true;
             }
@@ -787,7 +790,7 @@
  *  \brief Performs instance initialiation not requiring access to database.
  *  \sa Init(void)
  */
-TV::TV(void)
+TV::TV(PlaySettings *settings)
     : // Configuration variables from database
       baseFilters(""),
       db_channel_format("<num> <sign>"),
@@ -924,6 +927,7 @@
         kv[QString("FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
 
     MythDB::getMythDB()->GetSettings(kv);
+    settings->AddToMap(kv);
 
     // convert from minutes to ms.
     db_idle_timeout        = kv["LiveTVIdleTimeout"].toInt() * 60 * 1000;
@@ -1712,7 +1716,7 @@
 }
 
 
-int TV::Playback(const ProgramInfo &rcinfo)
+int TV::Playback(const ProgramInfo &rcinfo, PlaySettings *settings)
 {
     wantsToQuit   = false;
     jumpToProgram = false;
@@ -1726,7 +1730,7 @@
         return 0;
     }
 
-    mctx->SetPlayingInfo(&rcinfo);
+    mctx->SetPlayingInfo(&rcinfo, settings);
     mctx->SetInitialTVState(false);
     ScheduleStateChange(mctx);
 
@@ -1809,7 +1813,8 @@
 
     if (fileexists)
     {
-        Playback(pginfo);
+        PlaySettings settings("Default");
+        Playback(pginfo, &settings);
         retval = 1;
     }
 
@@ -2154,7 +2159,9 @@
         {
             OSD *osd = GetOSDLock(ctx);
             ctx->LockPlayingInfo(__FILE__, __LINE__);
-            if (osd && (PlayGroup::GetCount() > 0))
+            if (ctx->playingInfo->playgroup != "Default" &&
+                ctx->playingInfo->playgroup != "Videos" &&
+                osd && (PlayGroup::GetCount() > 0))
                 osd->SetSettingsText(tr("%1 Settings")
                     .arg(tv_i18n(ctx->playingInfo->playgroup)), 3);
             ctx->UnlockPlayingInfo(__FILE__, __LINE__);
@@ -5169,7 +5176,7 @@
         return false;
     }
 
-    InitUDPNotifyEvent();
+    InitUDPNotifyEvent(ctx->settings);
     bool ok = false;
     if (ctx->IsNullVideoDesired())
     {
@@ -11827,11 +11834,11 @@
         GetMythUI()->RestoreScreensaver();
 }
 
-void TV::InitUDPNotifyEvent(void)
+void TV::InitUDPNotifyEvent(PlaySettings *settings)
 {
     if (db_udpnotify_port && !udpnotify)
     {
-        udpnotify = new UDPNotify(db_udpnotify_port);
+        udpnotify = new UDPNotify(db_udpnotify_port, settings);
         connect(udpnotify,
                 SIGNAL(AddUDPNotifyEvent(
                         const QString&,const UDPNotifyOSDSet*)),
Index: libs/libmythtv/videodisplayprofile.h
===================================================================
--- libs/libmythtv/videodisplayprofile.h	(revision 24189)
+++ libs/libmythtv/videodisplayprofile.h	(working copy)
@@ -13,6 +13,8 @@
 
 #include "mythcontext.h"
 
+class PlaySettings;
+
 typedef QMap<QString,QString>     pref_map_t;
 typedef QMap<QString,QStringList> safe_map_t;
 typedef QStringList               safe_list_t;
@@ -80,7 +82,7 @@
 class MPUBLIC VideoDisplayProfile
 {
   public:
-    VideoDisplayProfile();
+    VideoDisplayProfile(PlaySettings *settings);
     ~VideoDisplayProfile();
 
     void SetInput(const QSize &size);
@@ -124,7 +126,8 @@
     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,
Index: libs/libmythtv/videoout_null.cpp
===================================================================
--- libs/libmythtv/videoout_null.cpp	(revision 24189)
+++ libs/libmythtv/videoout_null.cpp	(working copy)
@@ -27,8 +27,8 @@
     opts.priorities->insert("null", 10);
 }
 
-VideoOutputNull::VideoOutputNull(void) :
-    VideoOutput(), global_lock(QMutex::Recursive)
+VideoOutputNull::VideoOutputNull(PlaySettings *settings) :
+    VideoOutput(settings), global_lock(QMutex::Recursive)
 {
     VERBOSE(VB_PLAYBACK, "VideoOutputNull()");
     memset(&av_pause_frame, 0, sizeof(av_pause_frame));
Index: libs/libmythtv/videooutbase.cpp
===================================================================
--- libs/libmythtv/videooutbase.cpp	(revision 24189)
+++ libs/libmythtv/videooutbase.cpp	(working copy)
@@ -7,6 +7,7 @@
 #include "NuppelVideoPlayer.h"
 #include "videodisplayprofile.h"
 #include "decoderbase.h"
+#include "playsettings.h"
 
 #include "mythcontext.h"
 #include "mythverbose.h"
@@ -107,7 +108,8 @@
         PIPState pipState,
         const QSize   &video_dim, float        video_aspect,
         WId            win_id,    const QRect &display_rect,
-        float          video_prate,     WId    embed_id)
+        float          video_prate,     WId    embed_id,
+        PlaySettings *settings)
 {
     (void) codec_priv;
 
@@ -152,7 +154,7 @@
     QString renderer = QString::null;
     if (renderers.size() > 0)
     {
-        VideoDisplayProfile vprof;
+        VideoDisplayProfile vprof(settings);
         vprof.SetInput(video_dim);
 
         QString tmp = vprof.GetVideoRenderer();
@@ -180,32 +182,32 @@
 
 #ifdef USING_DIRECTFB
         if (renderer == "directfb")
-            vo = new VideoOutputDirectfb();
+            vo = new VideoOutputDirectfb(settings);
 #endif // USING_DIRECTFB
 
 #ifdef USING_MINGW
         if (renderer == "direct3d")
-            vo = new VideoOutputD3D();
+            vo = new VideoOutputD3D(settings);
 #endif // USING_MINGW
 
 #ifdef Q_OS_MACX
         if (osxlist.contains(renderer))
-            vo = new VideoOutputQuartz(codec_id, codec_priv);
+            vo = new VideoOutputQuartz(settings, codec_id, codec_priv);
 #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(codec_id);
+            vo = new VideoOutputVDPAU(settings, codec_id);
 #endif // USING_VDPAU
 
 #ifdef USING_XV
         if (xvlist.contains(renderer))
-            vo = new VideoOutputXv(codec_id);
+            vo = new VideoOutputXv(settings, codec_id);
 #endif // USING_XV
 
         if (vo)
@@ -302,7 +304,7 @@
  * \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
     db_display_dim(0,0),
     db_aspectoverride(kAspect_Off),     db_adjustfill(kAdjustFill_Off),
@@ -336,35 +338,37 @@
     display_res(NULL),
 
     // Physical display
-    monitor_sz(640,480),                monitor_dim(400,300)
+    monitor_sz(640,480),                monitor_dim(400,300),
 
+    settings(_settings)
+
 {
     bzero(&pip_tmp_image, sizeof(pip_tmp_image));
-    db_display_dim = QSize(gContext->GetNumSetting("DisplaySizeWidth",  0),
-                           gContext->GetNumSetting("DisplaySizeHeight", 0));
+    db_display_dim = QSize(settings->GetNumSetting("DisplaySizeWidth",  0),
+                           settings->GetNumSetting("DisplaySizeHeight", 0));
 
     db_pict_attr[kPictureAttribute_Brightness] =
-        gContext->GetNumSetting("PlaybackBrightness", 50);
+        settings->GetNumSetting("PlaybackBrightness", 50);
     db_pict_attr[kPictureAttribute_Contrast] =
-        gContext->GetNumSetting("PlaybackContrast",   50);
+        settings->GetNumSetting("PlaybackContrast",   50);
     db_pict_attr[kPictureAttribute_Colour] =
-        gContext->GetNumSetting("PlaybackColour",     50);
+        settings->GetNumSetting("PlaybackColour",     50);
     db_pict_attr[kPictureAttribute_Hue] =
-        gContext->GetNumSetting("PlaybackHue",         0);
+        settings->GetNumSetting("PlaybackHue",         0);
 
     db_aspectoverride = (AspectOverrideMode)
-        gContext->GetNumSetting("AspectOverride",      0);
+        settings->GetNumSetting("AspectOverride",      0);
     db_adjustfill = (AdjustFillMode)
-        gContext->GetNumSetting("AdjustFill",          0);
+        settings->GetNumSetting("AdjustFill",          0);
     db_letterbox_colour = (LetterBoxColour)
-        gContext->GetNumSetting("LetterboxColour",     0);
+        settings->GetNumSetting("LetterboxColour",     0);
     db_use_picture_controls =
-        gContext->GetNumSetting("UseOutputPictureControls", 0);
+        settings->GetNumSetting("UseOutputPictureControls", 0);
 
     if (!gContext->IsDatabaseIgnored())
-        db_vdisp_profile = new VideoDisplayProfile();
+        db_vdisp_profile = new VideoDisplayProfile(settings);
 
-    windows.push_back(VideoOutWindow());
+    windows.push_back(VideoOutWindow(settings));
 }
 
 /**
@@ -433,12 +437,12 @@
     return QString::null;
 }
 
-bool VideoOutput::IsPreferredRenderer(QSize video_size)
+bool VideoOutput::IsPreferredRenderer(QSize video_size, PlaySettings *settings)
 {
     if (!db_vdisp_profile || (video_size == windows[0].GetVideoDispDim()))
         return true;
 
-    VideoDisplayProfile vdisp;
+    VideoDisplayProfile vdisp(settings);
     vdisp.SetInput(video_size);
     QString new_rend = vdisp.GetVideoRenderer();
     if (new_rend.isEmpty())
Index: libs/libmythtv/videooutwindow.h
===================================================================
--- libs/libmythtv/videooutwindow.h	(revision 24189)
+++ libs/libmythtv/videooutwindow.h	(working copy)
@@ -16,11 +16,12 @@
 #include "videoouttypes.h"
 
 class NuppelVideoPlayer;
+class PlaySettings;
 
 class VideoOutWindow
 {
   public:
-    VideoOutWindow();
+    VideoOutWindow(PlaySettings *settings);
 
     bool Init(const QSize &new_video_dim, float aspect,
               const QRect &new_display_visible_rect,
@@ -162,6 +163,8 @@
     bool     allowpreviewepg;
     PIPState pip_state;
 
+    PlaySettings *settings;
+
     // Constants
     static const float kManualZoomMaxHorizontalZoom;
     static const float kManualZoomMaxVerticalZoom;
Index: libs/libmythtv/videoout_directfb.h
===================================================================
--- libs/libmythtv/videoout_directfb.h	(revision 24189)
+++ libs/libmythtv/videoout_directfb.h	(working copy)
@@ -12,7 +12,7 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputDirectfb();
+    VideoOutputDirectfb(PlaySettings *settings);
     ~VideoOutputDirectfb();
 
     bool Init(int width, int height, float aspect, WId winid,
Index: libs/libmythtv/playercontext.h
===================================================================
--- libs/libmythtv/playercontext.h	(revision 24189)
+++ libs/libmythtv/playercontext.h	(working copy)
@@ -27,6 +27,7 @@
 class LiveTVChain;
 class MythDialog;
 class QPainter;
+class PlaySettings;
 
 typedef enum
 {
@@ -90,7 +91,7 @@
     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; }
@@ -145,6 +146,7 @@
     LiveTVChain        *tvchain;
     RingBuffer         *buffer;
     ProgramInfo        *playingInfo; ///< Currently playing info
+    PlaySettings       *settings; // corresponding to playingInfo
     long long           playingLen;  ///< Initial CalculateLength()
     bool                nohardwaredecoders; // < Disable use of VDPAU decoding
     bool                decoding;    ///< Video decoder thread started
Index: libs/libmythtv/vsync.h
===================================================================
--- libs/libmythtv/vsync.h	(revision 24189)
+++ libs/libmythtv/vsync.h	(working copy)
@@ -101,6 +101,7 @@
 
     // documented in vsync.cpp
     static VideoSync *BestMethod(VideoOutput*,
+                                 PlaySettings *settings,
                                  uint frame_interval, uint refresh_interval,
                                  bool interlaced);
   protected:
Index: libs/libmythtv/videoout_xv.h
===================================================================
--- libs/libmythtv/videoout_xv.h	(revision 24189)
+++ libs/libmythtv/videoout_xv.h	(working copy)
@@ -51,7 +51,7 @@
     friend class XvMCOSD;
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputXv(MythCodecID av_codec_id);
+    VideoOutputXv(PlaySettings *settings, MythCodecID av_codec_id);
    ~VideoOutputXv();
 
     bool Init(int width, int height, float aspect, WId winid,
@@ -109,9 +109,11 @@
     static MythCodecID GetBestSupportedCodec(uint width, uint height,
                                              uint osd_width, uint osd_height,
                                              uint stream_type, int xvmc_chroma,
-                                             bool test_surface, bool force_xv);
+                                             bool test_surface, bool force_xv,
+                                             PlaySettings *settings);
 
     static int GrabSuitableXvPort(MythXDisplay* disp, Window root,
+                                  PlaySettings *settings,
                                   MythCodecID type,
                                   uint width, uint height,
                                   bool &xvsetdefaults,
Index: libs/libmythtv/videoout_xv.cpp
===================================================================
--- libs/libmythtv/videoout_xv.cpp	(revision 24189)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -166,8 +166,8 @@
  * \see VideoOutput, VideoBuffers
  *
  */
-VideoOutputXv::VideoOutputXv(MythCodecID codec_id)
-    : VideoOutput(),
+VideoOutputXv::VideoOutputXv(PlaySettings *settings, MythCodecID codec_id)
+    : VideoOutput(settings),
       myth_codec_id(codec_id), video_output_subtype(XVUnknown),
       global_lock(QMutex::Recursive),
 
@@ -408,6 +408,7 @@
  * \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,
@@ -492,7 +493,7 @@
     }
 
     // figure out if we want chromakeying..
-    VideoDisplayProfile vdp;
+    VideoDisplayProfile vdp(settings);
     vdp.SetInput(QSize(width, height));
     bool check_for_colorkey = (vdp.GetOSDRenderer() == "chromakey");
 
@@ -785,7 +786,7 @@
     disp->StartLog();
     QString adaptor_name = QString::null;
     const QSize video_dim = windows[0].GetVideoDim();
-    xv_port = GrabSuitableXvPort(disp, disp->GetRoot(), mcodecid,
+    xv_port = GrabSuitableXvPort(disp, disp->GetRoot(), settings, mcodecid,
                                  video_dim.width(), video_dim.height(),
                                  xv_set_defaults,
                                  xvmc_chroma, &xvmc_surf_info, &adaptor_name);
@@ -864,7 +865,7 @@
     disp->StartLog();
     QString adaptor_name = QString::null;
     const QSize video_dim = windows[0].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, 0, NULL, &adaptor_name);
     if (xv_port == -1)
@@ -1018,7 +1019,8 @@
     uint width,       uint height,
     uint osd_width,   uint osd_height,
     uint stream_type, int xvmc_chroma,
-    bool test_surface, bool force_xv)
+    bool test_surface, bool force_xv,
+    PlaySettings *settings)
 {
     (void)width, (void)height, (void)osd_width, (void)osd_height;
     (void)stream_type, (void)xvmc_chroma, (void)test_surface;
@@ -1029,7 +1031,7 @@
         return ret;
 
 #ifdef USING_XVMC
-    VideoDisplayProfile vdp;
+    VideoDisplayProfile vdp(settings);
     vdp.SetInput(QSize(width, height));
     QString dec = vdp.GetDecoder();
     if ((dec == "libmpeg2") || (dec == "ffmpeg"))
@@ -1079,7 +1081,8 @@
 
         ok = false;
         bool dummy;
-        int port = GrabSuitableXvPort(disp, disp->GetRoot(), ret, width, height,
+        int port = GrabSuitableXvPort(disp, disp->GetRoot(), settings,
+                                      ret, width, height,
                                       dummy, xvmc_chroma, &info);
         if (port >= 0)
         {
Index: libs/libmythtv/udpnotify.cpp
===================================================================
--- libs/libmythtv/udpnotify.cpp	(revision 24189)
+++ libs/libmythtv/udpnotify.cpp	(working copy)
@@ -31,6 +31,7 @@
 #include "udpnotify.h"
 #include "mythcontext.h"
 #include "mythverbose.h"
+#include "playsettings.h"
 
 UDPNotifyOSDSet::UDPNotifyOSDSet(const QString &name, uint timeout)
     : m_name(name), m_timeout(timeout)
@@ -73,7 +74,7 @@
 
 /////////////////////////////////////////////////////////////////////////
 
-UDPNotify::UDPNotify(uint udp_port) :
+UDPNotify::UDPNotify(uint udp_port, PlaySettings *settings) :
     m_socket(new QUdpSocket()), m_db_osd_udpnotify_timeout(5)
 {
     connect(m_socket, SIGNAL(readyRead()),
@@ -81,7 +82,7 @@
 
     m_socket->bind(udp_port);
 
-    m_db_osd_udpnotify_timeout = gContext->GetNumSetting("OSDNotifyTimeout", 5);
+    m_db_osd_udpnotify_timeout = settings->GetNumSetting("OSDNotifyTimeout", 5);
 }
 
 void UDPNotify::deleteLater(void)
Index: libs/libmythtv/videooutbase.h
===================================================================
--- libs/libmythtv/videooutbase.h	(revision 24189)
+++ libs/libmythtv/videooutbase.h	(working copy)
@@ -29,6 +29,7 @@
 class FilterChain;
 class FilterManager;
 class OpenGLContextGLX;
+class PlaySettings;
 
 typedef QMap<NuppelVideoPlayer*,PIPLocation> PIPMap;
 
@@ -49,9 +50,10 @@
         PIPState       pipState,
         const QSize   &video_dim, float        video_aspect,
         WId            win_id,    const QRect &display_rect,
-        float video_prate,        WId          embed_id);
+        float video_prate,        WId          embed_id,
+        PlaySettings *settings);
 
-    VideoOutput();
+    VideoOutput(PlaySettings *settings);
     virtual ~VideoOutput();
 
     virtual bool Init(int width, int height, float aspect,
@@ -59,7 +61,7 @@
                       int winh, WId embedid = 0);
     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);
@@ -328,6 +330,8 @@
     // Display information
     QSize monitor_sz;
     QSize monitor_dim;
+
+    PlaySettings *settings;
 };
 
 #endif
Index: libs/libmythtv/textsubtitleparser.cpp
===================================================================
--- libs/libmythtv/textsubtitleparser.cpp	(revision 24189)
+++ libs/libmythtv/textsubtitleparser.cpp	(working copy)
@@ -21,6 +21,7 @@
 #include "RingBuffer.h"
 #include "textsubtitleparser.h"
 #include "xine_demux_sputext.h"
+#include "playsettings.h"
 
 bool operator<(const text_subtitle_t& left,
                const text_subtitle_t& right)
@@ -112,7 +113,8 @@
     m_subtitles.clear();
 }
 
-bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target)
+bool TextSubtitleParser::LoadSubtitles(QString fileName, TextSubtitles &target,
+                                       PlaySettings *settings)
 {
     demux_sputext_t sub_data;
     sub_data.rbuffer = new RingBuffer(fileName, 0, false);
@@ -130,7 +132,7 @@
     target.SetFrameBasedTiming(!sub_data.uses_time);
 
     QTextCodec *textCodec = NULL;
-    QString codec = gContext->GetSetting("SubtitleCodec", "");
+    QString codec = settings->GetSetting("SubtitleCodec", "");
     if (!codec.isEmpty())
         textCodec = QTextCodec::codecForName(codec.toLatin1());
     if (!textCodec)
Index: libs/libmythtv/osd.cpp
===================================================================
--- libs/libmythtv/osd.cpp	(revision 24189)
+++ libs/libmythtv/osd.cpp	(working copy)
@@ -32,6 +32,7 @@
 #include "mythverbose.h"
 #include "util.h"
 #include "channelutil.h"
+#include "playsettings.h"
 
 #include "x11colors.h"
 #include "mythdirs.h"
@@ -42,7 +43,7 @@
 static char  *cc708_default_font_names[16];
 static bool   cc708_defaults_initialized = false;
 static QMutex cc708_init_lock;
-static void initialize_osd_fonts(void);
+static void initialize_osd_fonts(PlaySettings *settings);
 
 #define LOC QString("OSD: ")
 #define LOC_ERR QString("OSD, Error: ")
@@ -58,11 +59,12 @@
 const char *kOSDDialogInfo           = "infobox";
 const char *kOSDDialogEditChannel    = "channel_editor";
 
-OSD::OSD() :
+OSD::OSD(PlaySettings *_settings) :
     QObject(),                          m_listener(NULL),
+    settings(_settings),
     osdBounds(),                        frameint(0),
     needPillarBox(false),
-    themepath(FindTheme(gContext->GetSetting("OSDTheme"))),
+    themepath(FindTheme(settings->GetSetting("OSDTheme", ""))),
     wscale(1.0f),                       fscale(1.0f),
     m_themeinfo(new ThemeInfo(themepath)),
     m_themeaspect(4.0f/3.0f),
@@ -172,7 +174,7 @@
     drawSurface = new OSDSurface(osd_bounds.width(), osd_bounds.height());
 
     if (!cc708_defaults_initialized)
-        initialize_osd_fonts();
+        initialize_osd_fonts(settings);
 
     for (uint i = 0; i < 16; i++)
         cc708fontnames[i] = cc708_default_font_names[i];
@@ -185,7 +187,7 @@
     if (themepath.isEmpty())
     {
         VERBOSE(VB_IMPORTANT, "Couldn't find OSD theme: "
-                <<gContext->GetSetting("OSDTheme"));
+                <<settings->GetSetting("OSDTheme", ""));
         InitDefaults();
         return;
     }
@@ -194,7 +196,7 @@
     if (!LoadTheme())
     {
         VERBOSE(VB_IMPORTANT, "Couldn't load OSD theme: "
-                <<gContext->GetSetting("OSDTheme")<<" at "<<themepath);
+                <<settings->GetSetting("OSDTheme", "")<<" at "<<themepath);
     }
 
     InitDefaults();
@@ -238,7 +240,7 @@
         QString name = "cc_font";
         int fontsize = m_themeinfo->BaseRes()->height() / 27;
 
-        ccfont = LoadFont(gContext->GetSetting("OSDCCFont"), fontsize);
+        ccfont = LoadFont(settings->GetSetting("OSDCCFont", ""), fontsize);
 
         if (ccfont)
             fontMap[name] = ccfont;
@@ -274,7 +276,7 @@
 
     OSDTypeCC *ccpage =
         new OSDTypeCC(name, ccfont, sub_xoff, sub_yoff,
-                      sub_dispw, sub_disph, wmult, hmult);
+                      sub_dispw, sub_disph, wmult, hmult, settings);
     container->AddType(ccpage);
     return true;
 }
@@ -293,7 +295,7 @@
 
     // Create fonts...
     TTFFont* ccfonts[48];
-    uint z = gContext->GetNumSetting("OSDCC708TextZoom", 100) *
+    uint z = settings->GetNumSetting("OSDCC708TextZoom", 100) *
                     m_themeinfo->BaseRes()->height();
     uint fontsizes[3] = { z / 3600, z / 2900, z / 2200 };
     for (uint i = 0; i < 48; i++)
@@ -360,7 +362,7 @@
     if (!font)
     {
         int fontsize = (size->height() - (2 * safe_y)) / 26;
-        font = LoadFont(gContext->GetSetting("OSDCCFont"), fontsize);
+        font = LoadFont(settings->GetSetting("OSDCCFont", ""), fontsize);
 
         if (font)
             fontMap[fontname] = font;
@@ -468,7 +470,8 @@
     TTFFont *font = GetFont(fontname);
     if (!font)
     {
-        font = LoadFont(gContext->GetSetting("OSDCCFont"), SUBTITLE_FONT_SIZE);
+        font = LoadFont(settings->GetSetting("OSDCCFont", ""),
+                        SUBTITLE_FONT_SIZE);
 
         if (font)
         {
@@ -536,7 +539,7 @@
 
     if (!actfont)
     {
-        actfont = LoadFont(gContext->GetSetting("OSDFont"), 16);
+        actfont = LoadFont(settings->GetSetting("OSDFont", ""), 16);
 
         if (actfont)
             fontMap["treemenulistfont"] = actfont;
@@ -684,8 +687,8 @@
     if (dir.exists())
     {
         VERBOSE(VB_IMPORTANT, QString("Couldn't find OSD theme: %1. "
-                "Switching to default.").arg(gContext->GetSetting("OSDTheme")));
-        gContext->OverrideSettingForSession("OSDTheme", "BlackCurves-OSD");
+                                      "Switching to default.").arg(settings->GetSetting("OSDTheme", "")));
+        settings->OverrideSetting/*ForSession*/("OSDTheme", "BlackCurves-OSD");
         return testdir;
     }
 
@@ -852,7 +855,7 @@
 void OSD::parseFont(QDomElement &element)
 {
     QString name;
-    QString fontfile = gContext->GetSetting("OSDFont");
+    QString fontfile = settings->GetSetting("OSDFont", "");
     int size = -1;
     int sizeSmall = -1;
     int sizeBig = -1;
@@ -930,7 +933,7 @@
         return;
     }
 
-    QString fontSizeType = gContext->GetSetting("OSDThemeFontSizeType",
+    QString fontSizeType = settings->GetSetting("OSDThemeFontSizeType",
                                                 "default");
     if (fontSizeType == "small")
     {
@@ -3111,16 +3114,16 @@
     return QRect(xoffset, yoffset, displaywidth, displayheight);
 }
 
-#define OSD_STRDUP(X) strdup(gContext->GetSetting(X).toLocal8Bit().constData())
+#define OSD_STRDUP(X) strdup(settings->GetSetting(X, "").toLocal8Bit().constData())
 
-static void initialize_osd_fonts(void)
+static void initialize_osd_fonts(PlaySettings *settings)
 {
     QMutexLocker locker(&cc708_init_lock);
     if (cc708_defaults_initialized)
         return;
     cc708_defaults_initialized = true;
 
-    QString default_font_type = gContext->GetSetting(
+    QString default_font_type = settings->GetSetting(
         "OSDCC708DefaultFontType", "MonoSerif");
 
     // 0
Index: libs/libmythtv/videoout_quartz.h
===================================================================
--- libs/libmythtv/videoout_quartz.h	(revision 24189)
+++ libs/libmythtv/videoout_quartz.h	(working copy)
@@ -3,6 +3,7 @@
 
 class DVDV;
 struct QuartzData;
+class PlaySettings;
 
 #include "videooutbase.h"
 
@@ -10,7 +11,8 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputQuartz(MythCodecID av_codec_id, void *codec_priv);
+    VideoOutputQuartz(PlaySettings *settings, MythCodecID av_codec_id,
+                      void *codec_priv);
    ~VideoOutputQuartz();
 
     bool Init(int width, int height, float aspect, WId winid,
@@ -51,7 +53,7 @@
     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(myth_codec_id); }
 
Index: libs/libmythtv/videodisplayprofile.cpp
===================================================================
--- libs/libmythtv/videodisplayprofile.cpp	(revision 24189)
+++ libs/libmythtv/videodisplayprofile.cpp	(working copy)
@@ -8,6 +8,7 @@
 #include "mythverbose.h"
 #include "videooutbase.h"
 #include "avformatdecoder.h"
+#include "playsettings.h"
 
 bool ProfileItem::IsMatch(const QSize &size, float rate) const
 {
@@ -212,7 +213,7 @@
 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 @@
     init_statics();
 
     QString hostname    = gContext->GetHostName();
-    QString cur_profile = GetDefaultProfileName(hostname);
+    QString cur_profile = GetDefaultProfileName(hostname, settings);
     uint    groupid     = GetProfileGroupID(cur_profile, hostname);
 
     item_list_t items = LoadDB(groupid);
@@ -772,9 +773,11 @@
     return list;
 }
 
-QString VideoDisplayProfile::GetDefaultProfileName(const QString &hostname)
+QString VideoDisplayProfile::GetDefaultProfileName(const QString &hostname,
+                                                   PlaySettings *settings)
 {
     QString tmp =
+        settings ? settings->GetSetting("DefaultVideoPlaybackProfile", "") :
         gContext->GetSettingOnHost("DefaultVideoPlaybackProfile", hostname);
 
     QStringList profiles = GetProfiles(hostname);
Index: libs/libmythtv/udpnotify.h
===================================================================
--- libs/libmythtv/udpnotify.h	(revision 24189)
+++ libs/libmythtv/udpnotify.h	(working copy)
@@ -20,6 +20,7 @@
 class QByteArray;
 class QUdpSocket;
 class QDomElement;
+class PlaySettings;
 
 class UDPNotifyOSDSet
 {
@@ -54,7 +55,7 @@
     Q_OBJECT
 
   public:
-    UDPNotify(uint udp_port);
+    UDPNotify(uint udp_port, PlaySettings *settings);
 
   signals:
     void AddUDPNotifyEvent(const QString &name, const UDPNotifyOSDSet*);
Index: libs/libmythtv/videoout_null.h
===================================================================
--- libs/libmythtv/videoout_null.h	(revision 24189)
+++ libs/libmythtv/videoout_null.h	(working copy)
@@ -9,7 +9,7 @@
 {
   public:
     static void GetRenderOptions(render_opts &opts, QStringList &cpudeints);
-    VideoOutputNull();
+    VideoOutputNull(PlaySettings *settings);
    ~VideoOutputNull();
 
     bool Init(int width, int height, float aspect, WId winid,
Index: libs/libmyth/settings.cpp
===================================================================
--- libs/libmyth/settings.cpp	(revision 24189)
+++ libs/libmyth/settings.cpp	(working copy)
@@ -235,6 +235,20 @@
     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 @@
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -327,6 +342,8 @@
 
     widget->setLayout(layout);
 
+    setValue(getValue());
+
     return widget;
 }
 
@@ -336,6 +353,7 @@
     {
         bxwidget = NULL;
         edit     = NULL;
+        labelWidget = NULL;
     }
 }
 
@@ -373,6 +391,26 @@
     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 @@
 
 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 @@
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -506,6 +547,8 @@
 
     widget->setLayout(layout);
 
+    setValue(intValue());
+
     return widget;
 }
 
@@ -515,12 +558,18 @@
     {
         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 @@
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":     ");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     bxwidget = widget;
@@ -659,8 +709,12 @@
             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 @@
 
     widget->setLayout(layout);
 
+    setValue(current);
+
     return widget;
 }
 
@@ -682,6 +738,7 @@
     {
         bxwidget = NULL;
         cbwidget = NULL;
+        labelWidget = NULL;
     }
 }
 
@@ -717,6 +774,7 @@
 
     if (rw)
     {
+        changeLabel(newValue);
         Setting::setValue(newValue);
         if (cbwidget)
             cbwidget->setCurrentIndex(current);
@@ -727,17 +785,33 @@
 {
     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)
     {
         cbwidget->insertItem(label);
     }
 
+    if (special_formatting)
+    {
+        changeOnSpecial = true;
+        specialLabel = label;
+    }
+
     SelectSetting::addSelection(label, value, select);
 
     if (cbwidget && isSet)
@@ -934,6 +1008,69 @@
     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) 
@@ -1121,6 +1258,24 @@
     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();
@@ -1143,6 +1298,7 @@
     bxwidget   = NULL;
     imagelabel = NULL;
     combo      = NULL;
+    labelWidget = NULL;
 }
 
 void ImageSelectSetting::imageSet(int num)
@@ -1190,6 +1346,7 @@
         QLabel *label = new QLabel();
         label->setText(getLabel() + ":");
         layout->addWidget(label);
+        labelWidget = label;
     }
 
     combo = new MythComboBox(false);
@@ -1236,6 +1393,10 @@
     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()));
@@ -1246,9 +1407,20 @@
 
     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)
Index: libs/libmyth/audiosettings.cpp
===================================================================
--- libs/libmyth/audiosettings.cpp	(revision 24189)
+++ libs/libmyth/audiosettings.cpp	(working copy)
@@ -6,6 +6,7 @@
  */
 
 #include "audiosettings.h"
+#include "playsettings.h"
 
 // startup_upmixer 
 AudioSettings::AudioSettings() :
@@ -18,6 +19,7 @@
     set_initial_vol(false),
     use_passthru(false),
     source(AUDIOOUTPUT_UNKNOWN),
+    psettings(0),
     upmixer(0)
 {
 }
@@ -32,6 +34,7 @@
     set_initial_vol(other.set_initial_vol),
     use_passthru(other.use_passthru),
     source(other.source),
+    psettings(other.psettings),
     upmixer(other.upmixer)
 {
 }
@@ -46,6 +49,7 @@
     AudioOutputSource audio_source,
     bool audio_set_initial_vol,
     bool audio_use_passthru,
+    PlaySettings *_psettings,
     int upmixer_startup) :
     main_device(audio_main_device),
     passthru_device(audio_passthru_device),
@@ -56,8 +60,14 @@
     set_initial_vol(audio_set_initial_vol),
     use_passthru(audio_use_passthru),
     source(audio_source),
+    psettings(_psettings),
     upmixer(upmixer_startup)
 {
+    if (!psettings)
+    {
+        QString name("Default");
+        psettings = new PlaySettings(name);
+    }
 }
 
 AudioSettings::AudioSettings(
@@ -66,6 +76,7 @@
     int   audio_codec,
     int   audio_samplerate,
     bool  audio_use_passthru,
+    PlaySettings *_psettings,
     int   upmixer_startup) :
     main_device(QString::null),
     passthru_device(QString::null),
@@ -76,10 +87,42 @@
     set_initial_vol(false),
     use_passthru(audio_use_passthru),
     source(AUDIOOUTPUT_UNKNOWN),
+    psettings(_psettings),
     upmixer(upmixer_startup)
 {
+    if (!psettings)
+    {
+        QString name("Default");
+        psettings = new PlaySettings(name);
+    }
 }
 
+AudioSettings::AudioSettings(
+    int   audio_bits, 
+    int   audio_channels, 
+    int   audio_codec,
+    int   audio_samplerate,
+    bool  audio_use_passthru,
+    int   upmixer_startup) :
+    main_device(QString::null),
+    passthru_device(QString::null),
+    bits(audio_bits),
+    channels(audio_channels),
+    codec(audio_codec),
+    samplerate(audio_samplerate),
+    set_initial_vol(false),
+    use_passthru(audio_use_passthru),
+    source(AUDIOOUTPUT_UNKNOWN),
+    psettings(NULL),
+    upmixer(upmixer_startup)
+{
+    if (!psettings)
+    {
+        QString name("Default");
+        psettings = new PlaySettings(name);
+    }
+}
+
 void AudioSettings::FixPassThrough(void)
 {
     if (passthru_device.isEmpty() || passthru_device.toLower() == "default")
Index: libs/libmyth/audiooutputbase.h
===================================================================
--- libs/libmyth/audiooutputbase.h	(revision 24189)
+++ libs/libmyth/audiooutputbase.h	(working copy)
@@ -155,6 +155,8 @@
     int orig_config_channels;
     int src_quality;
 
+    PlaySettings *psettings;
+
  private:
     // software volume
     template <class AudioDataType>
Index: libs/libmyth/audiooutputalsa.cpp
===================================================================
--- libs/libmyth/audiooutputalsa.cpp	(revision 24189)
+++ libs/libmyth/audiooutputalsa.cpp	(working copy)
@@ -8,6 +8,7 @@
 
 #include "mythcontext.h"
 #include "audiooutputalsa.h"
+#include "playsettings.h"
     
 #define LOC QString("ALSA: ")
 #define LOC_WARN QString("ALSA, Warning: ")
@@ -753,17 +754,17 @@
 {
     int volume;
 
-    mixer_control = gContext->GetSetting("MixerControl", "PCM");
+    mixer_control = psettings->GetSetting("MixerControl", "PCM");
 
     SetupMixer();
 
     if (mixer_handle != NULL && setstartingvolume)
     {
-        volume = gContext->GetNumSetting("MasterMixerVolume", 80);
+        volume = psettings->GetNumSetting("MasterMixerVolume", 80);
         SetCurrentVolume("Master", 0, volume);
         SetCurrentVolume("Master", 1, volume);
 
-        volume = gContext->GetNumSetting("PCMMixerVolume", 80);
+        volume = psettings->GetNumSetting("PCMMixerVolume", 80);
         SetCurrentVolume("PCM", 0, volume);
         SetCurrentVolume("PCM", 1, volume);
     }
@@ -780,7 +781,7 @@
 {
     int err;
 
-    QString alsadevice = gContext->GetSetting("MixerDevice", "default");
+    QString alsadevice = psettings->GetSetting("MixerDevice", "default");
     QString device = alsadevice.remove(QString("ALSA:"));
 
     if (mixer_handle != NULL)
Index: libs/libmyth/audiooutputca.cpp
===================================================================
--- libs/libmyth/audiooutputca.cpp	(revision 24189)
+++ libs/libmyth/audiooutputca.cpp	(working copy)
@@ -246,7 +246,7 @@
 
     if (internal_vol && set_initial_vol)
     {
-        QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
+        QString controlLabel = psettings->GetSetting("MixerControl", "PCM");
         controlLabel += "MixerVolume";
         SetCurrentVolume(gContext->GetNumSetting(controlLabel, 80));
     }
Index: libs/libmyth/volumebase.cpp
===================================================================
--- libs/libmyth/volumebase.cpp	(revision 24189)
+++ libs/libmyth/volumebase.cpp	(working copy)
@@ -8,13 +8,14 @@
 
 #include "volumebase.h"
 #include "mythcontext.h"
+#include "playsettings.h"
 
-VolumeBase::VolumeBase() :
+VolumeBase::VolumeBase(PlaySettings *_settings) :
     internal_vol(false), volume(80), 
-    current_mute_state(kMuteOff)
+    current_mute_state(kMuteOff), settings(_settings)
 {
     swvol = swvol_setting =
-        (gContext->GetSetting("MixerDevice", "default").toLower() == "software");
+        (settings->GetSetting("MixerDevice", "default").toLower() == "software");
 }
 
 bool VolumeBase::SWVolume(void)
@@ -39,7 +40,7 @@
     volume = max(min(value, 100), 0);
     UpdateVolume();
 
-    QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
+    QString controlLabel = settings->GetSetting("MixerControl", "PCM");
     controlLabel += "MixerVolume";
     gContext->SaveSetting(controlLabel, volume);    
 }
Index: libs/libmyth/settings.h
===================================================================
--- libs/libmyth/settings.h	(revision 24189)
+++ libs/libmyth/settings.h	(working copy)
@@ -134,10 +134,14 @@
 
 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 @@
 
     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 @@
   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 @@
     bool         relayEnabled;
     bool         sstep;
     QString      svtext;
+    QLabel      *labelWidget;
+    bool         changeOnSpecial;
 };
 
 class MPUBLIC SelectSetting : public Setting
@@ -277,6 +289,7 @@
         { 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 @@
 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);
@@ -338,15 +352,20 @@
 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;
@@ -415,7 +434,8 @@
     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);
@@ -426,9 +446,14 @@
                                    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);
@@ -440,6 +465,9 @@
     QLabel *imagelabel;
     MythComboBox *combo;
     float m_hmult, m_wmult;
+    bool          changeOnSpecial;
+    QString       specialLabel;
+    QLabel       *labelWidget;
 };
 
 class MPUBLIC BooleanSetting : public Setting
@@ -480,6 +508,56 @@
     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:
Index: libs/libmyth/audiooutputjack.cpp
===================================================================
--- libs/libmyth/audiooutputjack.cpp	(revision 24189)
+++ libs/libmyth/audiooutputjack.cpp	(working copy)
@@ -14,6 +14,7 @@
 #include "mythcontext.h"
 #include "audiooutputjack.h"
 #include "util.h"
+#include "playsettings.h"
 
 extern "C"
 {
@@ -213,7 +214,7 @@
 {
     int volume = 100;
     if (set_initial_vol)
-        volume = gContext->GetNumSetting("MasterMixerVolume", 80);
+        volume = psettings->GetNumSetting("MasterMixerVolume", 80);
 
     JACK_SetAllVolume(audioid, volume);
 }
Index: libs/libmyth/audiooutputbase.cpp
===================================================================
--- libs/libmyth/audiooutputbase.cpp	(revision 24189)
+++ libs/libmyth/audiooutputbase.cpp	(working copy)
@@ -15,11 +15,13 @@
 #include "audiooutputdigitalencoder.h"
 #include "SoundTouch.h"
 #include "freesurround.h"
+#include "playsettings.h"
 
 #define LOC QString("AO: ")
 #define LOC_ERR QString("AO, ERROR: ")
 
 AudioOutputBase::AudioOutputBase(const AudioSettings &settings) :
+    AudioOutput(settings.psettings),
     // protected
     effdsp(0),                  effdspstretched(0),
     audio_channels(-1),         audio_codec(CODEC_ID_NONE),
@@ -40,6 +42,8 @@
     set_initial_vol(settings.set_initial_vol),
     buffer_output_data_for_use(false),
 
+    psettings(settings.psettings),
+
     // private
     need_resampler(false),
 
@@ -82,17 +86,17 @@
     memset(tmp_buff,           0, sizeof(short) * kAudioTempBufSize);
     memset(&audiotime_updated, 0, sizeof(audiotime_updated));
     memset(audiobuffer,        0, sizeof(char)  * kAudioRingBufferSize);
-    orig_config_channels = gContext->GetNumSetting("MaxChannels", 2);
-    src_quality = gContext->GetNumSetting("AudioUpmixType", 2);
+    orig_config_channels = psettings->GetNumSetting("MaxChannels", 2);
+    src_quality = psettings->GetNumSetting("AudioUpmixType", 2);
         //Set default upsampling quality to medium if using stereo
     if (orig_config_channels == 2)
         src_quality = 1;
 
         // Handle override of SRC quality settings
-    if (gContext->GetNumSetting("AdvancedAudioSettings", false) &&
-        gContext->GetNumSetting("SRCQualityOverride", false))
+    if (psettings->GetNumSetting("AdvancedAudioSettings", false) &&
+        psettings->GetNumSetting("SRCQualityOverride", false))
     {
-        src_quality = gContext->GetNumSetting("SRCQuality", 1);
+        src_quality = psettings->GetNumSetting("SRCQuality", 1);
             // Extra test to keep backward compatibility with earlier SRC code setting
         if (src_quality > 2)
             src_quality = 2;
@@ -100,14 +104,18 @@
     }
 
     if (!settings.upmixer)
-        configured_audio_channels = gContext->GetNumSetting("AudioDefaultUpmix", false) ? orig_config_channels : 2;
+        configured_audio_channels =
+            psettings->GetNumSetting("AudioDefaultUpmix", false) ?
+            orig_config_channels : 2;
     else
         if (settings.upmixer == 1)
             configured_audio_channels = 2;
         else
             configured_audio_channels = 6;
 
-    allow_ac3_passthru = (orig_config_channels > 2) ? gContext->GetNumSetting("AC3PassThru", false) : false;
+    allow_ac3_passthru =
+        (orig_config_channels > 2) ?
+        psettings->GetNumSetting("AC3PassThru", false) : false;
 
     // You need to call Reconfigure from your concrete class.
     // Reconfigure(laudio_bits,       laudio_channels,
@@ -192,7 +200,7 @@
 
     const AudioSettings settings(audio_bits, source_audio_channels,
                                  audio_codec, source_audio_samplerate,
-                                 audio_passthru);
+                                 audio_passthru, psettings);
     Reconfigure(settings);
     return (configured_audio_channels == 6);
 }
@@ -278,7 +286,7 @@
     killaudio = false;
     pauseaudio = false;
     was_paused = true;
-    internal_vol = gContext->GetNumSetting("MythControlsVolume", 0);
+    internal_vol = settings.psettings->GetNumSetting("MythControlsVolume", 0);
 
     numlowbuffer = 0;
 
@@ -378,9 +386,10 @@
     // Only used for software volume
     if (set_initial_vol && internal_vol) 
     {
-        QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
+        QString controlLabel =
+            settings.psettings->GetSetting("MixerControl", "PCM");
         controlLabel += "MixerVolume";
-        volume = gContext->GetNumSetting(controlLabel, 80);
+        volume = settings.psettings->GetNumSetting(controlLabel, 80);
     }
 
     SyncVolume();
@@ -392,9 +401,10 @@
     if (audio_buffer_unused < 0)
         audio_buffer_unused = 0;
 
-    if (!gContext->GetNumSetting("AdvancedAudioSettings", false))
+    if (!settings.psettings->GetNumSetting("AdvancedAudioSettings", false))
         audio_buffer_unused = 0;
-    else if (!gContext->GetNumSetting("AggressiveSoundcardBuffer", false))
+    else if (!settings.psettings->GetNumSetting("AggressiveSoundcardBuffer",
+                                                false))
         audio_buffer_unused = 0;
 
     audbuf_timecode = 0;
@@ -410,7 +420,8 @@
         VERBOSE(VB_AUDIO, LOC + QString("create upmixer"));
         if (configured_audio_channels == 6)
         {
-            surround_mode = gContext->GetNumSetting("AudioUpmixType", 2);
+            surround_mode =
+                settings.psettings->GetNumSetting("AudioUpmixType", 2);
         }
 
         upmixer = new FreeSurround(
@@ -684,7 +695,7 @@
     volume = new_volume;
     if (save)
     {
-        QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
+        QString controlLabel = psettings->GetSetting("MixerControl", "PCM");
         controlLabel += "MixerVolume";
         gContext->SaveSetting(controlLabel, volume);
     }
Index: libs/libmyth/audiooutput.cpp
===================================================================
--- libs/libmyth/audiooutput.cpp	(revision 24189)
+++ libs/libmyth/audiooutput.cpp	(working copy)
@@ -6,6 +6,7 @@
 #include "mythconfig.h"
 #include "audiooutput.h"
 #include "compat.h"
+#include "playsettings.h"
 
 #include "audiooutputnull.h"
 #ifdef USING_MINGW
@@ -37,10 +38,28 @@
     bool set_initial_vol, bool audio_passthru,
     int upmixer_startup)
 {
+    QString str("Default");
+    PlaySettings psettings(str);
+    return OpenAudio(main_device, passthru_device, audio_bits,
+                     audio_channels, audio_codec, audio_samplerate,
+                     source, set_initial_vol, audio_passthru,
+                     &psettings, upmixer_startup);
+}
+
+AudioOutput *AudioOutput::OpenAudio(
+    const QString &main_device,
+    const QString &passthru_device,
+    int audio_bits, int audio_channels, 
+    int audio_codec, int audio_samplerate,
+    AudioOutputSource source,
+    bool set_initial_vol, bool audio_passthru,
+    PlaySettings *psettings,
+    int upmixer_startup)
+{
     AudioSettings settings(
         main_device, passthru_device, audio_bits,
         audio_channels, audio_codec, audio_samplerate, source,
-        set_initial_vol, audio_passthru, upmixer_startup);
+        set_initial_vol, audio_passthru, psettings, upmixer_startup);
 
     settings.FixPassThrough();
 
Index: libs/libmyth/libmyth.pro
===================================================================
--- libs/libmyth/libmyth.pro	(revision 24189)
+++ libs/libmyth/libmyth.pro	(working copy)
@@ -56,6 +56,9 @@
 SOURCES += recordingtypes.cpp remoteutil.cpp
 SOURCES += rawsettingseditor.cpp
 
+HEADERS += playsettings.h
+SOURCES += playsettings.cpp
+
 # remove when everything is switched to mythui
 SOURCES += virtualkeyboard_qt.cpp
 
Index: libs/libmyth/audiosettings.h
===================================================================
--- libs/libmyth/audiosettings.h	(revision 24189)
+++ libs/libmyth/audiosettings.h	(working copy)
@@ -12,6 +12,8 @@
 
 #include "mythexp.h"
 
+class PlaySettings;
+
 typedef enum {
     AUDIOOUTPUT_UNKNOWN,
     AUDIOOUTPUT_VIDEO,
@@ -34,6 +36,7 @@
         AudioOutputSource audio_source,
         bool              audio_set_initial_vol,
         bool              audio_use_passthru,
+        PlaySettings     *psettings,
         int               upmixer_startup = 0);
 
     AudioSettings(int   audio_bits, 
@@ -41,8 +44,16 @@
                   int   audio_codec,
                   int   audio_samplerate,
                   bool  audio_use_passthru,
+                  PlaySettings *psettings,
                   int   upmixer_startup = 0);
 
+    AudioSettings(int   audio_bits, 
+                  int   audio_channels, 
+                  int   audio_codec,
+                  int   audio_samplerate,
+                  bool  audio_use_passthru,
+                  int   upmixer_startup = 0);
+
     void FixPassThrough(void);
     void TrimDeviceType(void);
 
@@ -61,6 +72,7 @@
     bool    set_initial_vol;
     bool    use_passthru;
     AudioOutputSource source;
+    PlaySettings *psettings;
     int     upmixer;
 };
 
Index: libs/libmyth/audiooutputoss.cpp
===================================================================
--- libs/libmyth/audiooutputoss.cpp	(revision 24189)
+++ libs/libmyth/audiooutputoss.cpp	(working copy)
@@ -27,6 +27,7 @@
 #include "mythcontext.h"
 #include "audiooutputoss.h"
 #include "util.h"
+#include "playsettings.h"
 
 AudioOutputOSS::AudioOutputOSS(const AudioSettings &settings) :
     AudioOutputBase(settings),
@@ -316,14 +317,14 @@
     mixerfd = -1;
     int volume = 0;
 
-    QString device = gContext->GetSetting("MixerDevice", "/dev/mixer");
+    QString device = psettings->GetSetting("MixerDevice", "/dev/mixer");
     if (device.toLower() == "software")
         return;
 
     QByteArray dev = device.toAscii();
     mixerfd = open(dev.constData(), O_RDONLY);
 
-    QString controlLabel = gContext->GetSetting("MixerControl", "PCM");
+    QString controlLabel = psettings->GetSetting("MixerControl", "PCM");
 
     if (controlLabel == "Master")
     {
@@ -344,7 +345,7 @@
     if (set_initial_vol)
     {
         int tmpVol;
-        volume = gContext->GetNumSetting("MasterMixerVolume", 80);
+        volume = psettings->GetNumSetting("MasterMixerVolume", 80);
         tmpVol = (volume << 8) + volume;
         int ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &tmpVol);
         if (ret < 0)
@@ -353,7 +354,7 @@
                     QString("Error Setting initial Master Volume") + ENO);
         }
 
-        volume = gContext->GetNumSetting("PCMMixerVolume", 80);
+        volume = psettings->GetNumSetting("PCMMixerVolume", 80);
         tmpVol = (volume << 8) + volume;
         ret = ioctl(mixerfd, MIXER_WRITE(SOUND_MIXER_PCM), &tmpVol);
         if (ret < 0)
Index: libs/libmyth/volumebase.h
===================================================================
--- libs/libmyth/volumebase.h	(revision 24189)
+++ libs/libmyth/volumebase.h	(working copy)
@@ -3,6 +3,8 @@
 
 #include "mythexp.h"
 
+class PlaySettings;
+
 typedef enum {
     kMuteOff = 0,
     kMuteLeft,
@@ -13,7 +15,7 @@
 class MPUBLIC VolumeBase
 {
   public:
-    VolumeBase();    
+    VolumeBase(PlaySettings *settings);    
     virtual ~VolumeBase() {};
 
     void SWVolume(bool set);
@@ -46,6 +48,7 @@
     MuteState current_mute_state;
     bool swvol;
     bool swvol_setting;
+    PlaySettings *settings;
 
 };
 
Index: libs/libmyth/mythwidgets.cpp
===================================================================
--- libs/libmyth/mythwidgets.cpp	(revision 24189)
+++ libs/libmyth/mythwidgets.cpp	(working copy)
@@ -223,7 +223,16 @@
         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;
     }
Index: libs/libmyth/audiooutput.h
===================================================================
--- libs/libmyth/audiooutput.h	(revision 24189)
+++ libs/libmyth/audiooutput.h	(working copy)
@@ -8,6 +8,8 @@
 #include "volumebase.h"
 #include "output.h"
 
+class PlaySettings;
+
 class MPUBLIC AudioOutput : public VolumeBase, public OutputListeners
 {
  public:
@@ -19,10 +21,19 @@
         int audio_codec, int audio_samplerate,
         AudioOutputSource source,
         bool set_initial_vol, bool audio_passthru,
+        PlaySettings *psettings,
         int upmixer_startup = 0);
+    static AudioOutput *OpenAudio(
+        const QString &audiodevice,
+        const QString &passthrudevice,
+        int audio_bits, int audio_channels, 
+        int audio_codec, int audio_samplerate,
+        AudioOutputSource source,
+        bool set_initial_vol, bool audio_passthru,
+        int upmixer_startup = 0);
 
-    AudioOutput() :
-        VolumeBase(),             OutputListeners(),
+    AudioOutput(PlaySettings *psettings) :
+        VolumeBase(psettings),    OutputListeners(),
         lastError(QString::null), lastWarn(QString::null) {}
 
     virtual ~AudioOutput() { };
Index: libs/libmyth/mythconfiggroups.cpp
===================================================================
--- libs/libmyth/mythconfiggroups.cpp	(revision 24189)
+++ libs/libmyth/mythconfiggroups.cpp	(working copy)
@@ -475,6 +475,7 @@
                                             Configurable *target)
 {
     VerifyLayout();
+    bool isDuplicate = triggerMap.values().contains(target);
     triggerMap[triggerValue] = target;
 
     if (!configStack)
@@ -484,7 +485,10 @@
         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)
Index: libs/libmyth/mythwidgets.h
===================================================================
--- libs/libmyth/mythwidgets.h	(revision 24189)
+++ libs/libmyth/mythwidgets.h	(working copy)
@@ -329,11 +329,19 @@
     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&);
 
Index: libs/libmyth/audiooutputpulse.cpp
===================================================================
--- libs/libmyth/audiooutputpulse.cpp	(revision 24189)
+++ libs/libmyth/audiooutputpulse.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include <QString>
 
 #include "audiooutputpulse.h"
+#include "playsettings.h"
 
 #define LOC     QString("PulseAudio: ")
 #define LOC_ERR QString("PulseAudio Error: ")
@@ -547,7 +548,7 @@
                                      (char*)"under");
     if (set_initial_vol)
     {
-        int volume = gContext->GetNumSetting("MasterMixerVolume", 80);
+        int volume = psettings->GetNumSetting("MasterMixerVolume", 80);
         pa_cvolume_set(&volume_control, audio_channels,
                        (float)volume * (float)PA_VOLUME_NORM / 100.0f);
     }
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 24189)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -41,7 +41,132 @@
 #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 + ")");
+
+    return obj;
+}
+
+static QString getDefault(Setting *obj)
+{
+    PlaySettingsCombinedStorage *storage =
+        dynamic_cast<PlaySettingsCombinedStorage *>(obj);
+    if (storage)
+        return storage->getDefault();
+    else
+        return "";
+}
+
 AudioOutputDevice::AudioOutputDevice() : HostComboBox("AudioOutputDevice", true)
 {
     setLabel(QObject::tr("Audio output device"));
@@ -103,32 +228,32 @@
     setHelpText(desc);
 }
 
-static HostComboBox *MaxAudioChannels()
+static Setting *MaxAudioChannels(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("MaxChannels",false);
+    CREATE_COMBOBOX_SETTING(gc, "MaxChannels", settings);
     gc->setLabel(QObject::tr("Speakers configuration"));
     gc->addSelection(QObject::tr("Stereo"), "2", true); // default
     gc->addSelection(QObject::tr("5.1"), "6");
     gc->setHelpText(
             QObject::tr(
                 "Set your audio configuration: Stereo or Surround."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AudioUpmix()
+static Setting *AudioUpmix(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AudioDefaultUpmix");
+    CREATE_CHECKBOX_SETTING(gc, "AudioDefaultUpmix", settings);
     gc->setLabel(QObject::tr("Upconvert stereo to 5.1 surround"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("MythTV can upconvert stereo to 5.1 audio. "
                                 "Set this option to enable it by default. "
                                 "You can enable or disable the upconversion during playback at anytime."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *AudioUpmixType()
+static Setting *AudioUpmixType(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("AudioUpmixType",false);
+    CREATE_COMBOBOX_SETTING(gc, "AudioUpmixType", settings);
     gc->setLabel(QObject::tr("Upmix"));
     gc->addSelection(QObject::tr("Fastest"), "0", true); // default
     gc->addSelection(QObject::tr("Good"), "1");
@@ -137,30 +262,30 @@
             QObject::tr(
                 "Set the audio surround upconversion quality. "
                 "'Fastest' is the least demanding on the CPU at the expense of quality."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AdvancedAudioSettings()
+static Setting *AdvancedAudioSettings(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AdvancedAudioSettings");
+    CREATE_CHECKBOX_SETTING(gc, "AdvancedAudioSettings", settings);
     gc->setLabel(QObject::tr("Advanced Audio Configuration"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("Enable extra audio settings."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *SRCQualityOverride()
+static Setting *SRCQualityOverride(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("SRCQualityOverride");
+    CREATE_CHECKBOX_SETTING(gc, "SRCQualityOverride", settings);
     gc->setLabel(QObject::tr("Override SRC quality"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("Override audio sample rate conversion quality"));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *SRCQuality()
+static Setting *SRCQuality(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("SRCQuality", false);
+    CREATE_COMBOBOX_SETTING(gc, "SRCQuality", settings);
     gc->setLabel(QObject::tr("Sample Rate Conversion"));
     gc->addSelection(QObject::tr("Disabled"), "-1");
     gc->addSelection(QObject::tr("Fastest"), "0");
@@ -170,12 +295,12 @@
                                 "\"Good\" (default) provides the best compromise between CPU usage "
                                 "and quality. \"Disabled\" let the audio card handle sample rate conversion. "
                                 "This only affects non 48kHz PCM audio."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *PassThroughOutputDevice()
+static Setting *PassThroughOutputDevice(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("PassThruOutputDevice", true);
+    CREATE_COMBOBOX1_SETTING(gc, "PassThruOutputDevice", settings, true);
 
     gc->setLabel(QObject::tr("Digital output device"));
     gc->addSelection(QObject::tr("Default"), "Default");
@@ -193,24 +318,24 @@
     gc->setHelpText(QObject::tr("Audio output device to use for digital audio. Default is the same as Audio output "
                     "device. This value is currently only used with ALSA "
                     "and DirectX sound output."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *MythControlsVolume()
+static Setting *MythControlsVolume(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("MythControlsVolume");
+    CREATE_CHECKBOX_SETTING(gc, "MythControlsVolume", settings);
     gc->setLabel(QObject::tr("Use internal volume controls"));
     gc->setValue(true);
     gc->setHelpText(QObject::tr("MythTV can control the PCM and master "
                     "mixer volume.  If you prefer to control the volume externally "
                     "(like your amplifier) or use an external mixer "
                     "program, disable this option."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *MixerDevice()
+static Setting *MixerDevice(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("MixerDevice", true);
+    CREATE_COMBOBOX1_SETTING(gc, "MixerDevice", settings, true);
     gc->setLabel(QObject::tr("Mixer Device"));
 
 #ifdef USING_OSS
@@ -236,15 +361,15 @@
                                 "the volume of all audio at the expense of a slight quality loss."));
 #endif
 
-    return gc;
+    return wrap(gc, settings);
 }
 
 static const char* MixerControlControls[] = { "PCM",
                                               "Master" };
 
-static HostComboBox *MixerControl()
+static Setting *MixerControl(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("MixerControl", true);
+    CREATE_COMBOBOX1_SETTING(gc, "MixerControl", settings, true);
     gc->setLabel(QObject::tr("Mixer Controls"));
     for (unsigned int i = 0; i < sizeof(MixerControlControls) / sizeof(char*);
          ++i)
@@ -254,23 +379,23 @@
     }
 
     gc->setHelpText(QObject::tr("Changing the volume adjusts the selected mixer."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostSlider *MixerVolume()
+static Setting *MixerVolume(PlaySettings *settings)
 {
-    HostSlider *gs = new HostSlider("MasterMixerVolume", 0, 100, 1);
+    CREATE_SLIDER_SETTING(gs, "MasterMixerVolume", settings, 0, 100, 1);
     gs->setLabel(QObject::tr("Master Mixer Volume"));
     gs->setValue(70);
     gs->setHelpText(QObject::tr("Initial volume for the Master Mixer.  "
                     "This affects all sound created by the sound card.  "
                     "Note: Do not set this too low."));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSlider *PCMVolume()
+static Setting *PCMVolume(PlaySettings *settings)
 {
-    HostSlider *gs = new HostSlider("PCMMixerVolume", 0, 100, 1);
+    CREATE_SLIDER_SETTING(gs, "PCMMixerVolume", settings, 0, 100, 1);
     gs->setLabel(QObject::tr("PCM Mixer Volume"));
     gs->setValue(70);
     gs->setHelpText(QObject::tr("Initial volume for PCM output.  Using the "
@@ -278,9 +403,9 @@
     return gs;
 }
 
-static HostCheckBox *IndividualMuteControl()
+static Setting *IndividualMuteControl(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("IndividualMuteControl");
+    CREATE_CHECKBOX_SETTING(gc, "IndividualMuteControl", settings);
     gc->setLabel(QObject::tr("Independent Muting of Left and Right Audio "
                  "Channels"));
     gc->setValue(false);
@@ -289,32 +414,32 @@
                     "original language on one channel, and a dubbed "
                     "version of the program on the other one.  This "
                     "modifies the behavior of the Mute key."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AC3PassThrough()
+static Setting *AC3PassThrough(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AC3PassThru");
+    CREATE_CHECKBOX_SETTING(gc, "AC3PassThru", settings);
     gc->setLabel(QObject::tr("Dolby Digital"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("Enable if your amplifier or sound decoder supports AC3/Dolby Digital. "
                                 "You must use a digital connection. Uncheck if using an analog connection."));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *DTSPassThrough()
+static Setting *DTSPassThrough(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("DTSPassThru");
+    CREATE_CHECKBOX_SETTING(gc, "DTSPassThru", settings);
     gc->setLabel(QObject::tr("DTS"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("Enable if your amplifier or sound decoder supports DTS. "
                                 "You must use a digital connection. Uncheck if using an analog connection"));
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostCheckBox *AggressiveBuffer()
+static Setting *AggressiveBuffer(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("AggressiveSoundcardBuffer");
+    CREATE_CHECKBOX_SETTING(gc, "AggressiveSoundcardBuffer", settings);
     gc->setLabel(QObject::tr("Aggressive Sound card Buffering"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr("If enabled, MythTV will pretend to have "
@@ -324,9 +449,9 @@
     return gc;
 }
 
-static HostCheckBox *DecodeExtraAudio()
+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 "
@@ -335,17 +460,17 @@
                     "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 GlobalLineEdit *AllRecGroupPassword()
@@ -442,25 +567,25 @@
     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()
@@ -478,9 +603,9 @@
     return bc;
 }
 
-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");
@@ -489,7 +614,7 @@
                     "have been flagged during Automatic Commercial Flagging "
                     "or by the mythcommflag program, or just notify that a "
                     "commercial has been detected."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static GlobalCheckBox *AutoCommercialFlag()
@@ -574,26 +699,26 @@
     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 Auto-Rewind Amount"));
     gs->setHelpText(QObject::tr("If set, 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"));
     gs->setHelpText(QObject::tr("If set, 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()
@@ -1395,11 +1520,16 @@
     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 = gContext->GetHostName();
     QStringList profiles = VideoDisplayProfile::GetProfiles(host);
@@ -1427,18 +1557,24 @@
         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);
@@ -1571,9 +1707,9 @@
     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 "
@@ -1581,12 +1717,12 @@
                     "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 "
@@ -1594,37 +1730,38 @@
                     "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 HostSpinBox *OSDGeneralTimeout()
+static Setting *OSDGeneralTimeout(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("OSDGeneralTimeout", 1, 30, 1);
+    CREATE_SPINBOX_SETTING(gs, "OSDGeneralTimeout", settings, 1, 30, 1, false);
     gs->setLabel(QObject::tr("General OSD time-out (sec)"));
     gs->setValue(2);
     gs->setHelpText(QObject::tr("Length of time an on-screen display "
                     "window will be visible."));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSpinBox *OSDProgramInfoTimeout()
+static Setting *OSDProgramInfoTimeout(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("OSDProgramInfoTimeout", 1, 30, 1);
+    CREATE_SPINBOX_SETTING(gs, "OSDProgramInfoTimeout", settings,
+                           1, 30, 1, false);
     gs->setLabel(QObject::tr("Program Info OSD time-out"));
     gs->setValue(3);
     gs->setHelpText(QObject::tr("Length of time the on-screen display "
                     "will display program information."));
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostSpinBox *OSDNotifyTimeout()
+static Setting *OSDNotifyTimeout(PlaySettings *settings)
 {
-    HostSpinBox *gs = new HostSpinBox("OSDNotifyTimeout", 1, 30, 1);
+    CREATE_SPINBOX_SETTING(gs, "OSDNotifyTimeout", settings, 1, 30, 1, false);
     gs->setLabel(QObject::tr("UDP Notify OSD time-out"));
     gs->setValue(5);
     gs->setHelpText(QObject::tr("How many seconds an on-screen display "
                     "will be active for UDP Notify events."));
-    return gs;
+    return wrap(gs, settings);
 }
 
 static HostSpinBox *ThemeCacheSize()
@@ -1668,9 +1805,9 @@
     return gc;
 }
 
-static HostComboBox *OSDFont()
+static Setting *OSDFont(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("OSDFont");
+    CREATE_COMBOBOX_SETTING(gc, "OSDFont", settings);
     gc->setLabel(QObject::tr("OSD font"));
     QDir ttf(GetFontsDir(), GetFontsNameFilter());
     gc->fillSelectionsFromDir(ttf, false);
@@ -1678,18 +1815,18 @@
     if (gc->findSelection(defaultOSDFont) > -1)
         gc->setValue(defaultOSDFont);
 
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HostComboBox *OSDCCFont()
+static Setting *OSDCCFont(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("OSDCCFont");
+    CREATE_COMBOBOX_SETTING(gc, "OSDCCFont", settings);
     gc->setLabel(QObject::tr("CC font"));
     QDir ttf(GetFontsDir(), GetFontsNameFilter());
     gc->fillSelectionsFromDir(ttf, false);
     gc->setHelpText(QObject::tr("Closed Caption font"));
 
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostComboBox __attribute__ ((unused)) *DecodeVBIFormat()
@@ -1710,19 +1847,20 @@
     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("Text zoom percentage"));
     gs->setValue(100);
     gs->setHelpText(QObject::tr("Use this to enlarge or shrink captions."));
 
-    return gs;
+    return wrap(gs, settings);
 }
 
-static HostComboBox *OSDCC708DefaultFontType(void)
+static Setting *OSDCC708DefaultFontType(PlaySettings *settings)
 {
-    HostComboBox *hc = new HostComboBox("OSDCC708DefaultFontType");
+    CREATE_COMBOBOX_SETTING(hc, "OSDCC708DefaultFontType", settings);
     hc->setLabel(QObject::tr("Default Caption Font Type"));
     hc->setHelpText(
         QObject::tr("This allows you to set which font type to use "
@@ -1745,17 +1883,21 @@
     };
     for (uint i = 0; i < 7; ++i)
         hc->addSelection(typeNames[i], types[i]);
-    return hc;
+    return wrap(hc, settings);
 }
 
-static VerticalConfigurationGroup *OSDCC708Settings(void)
+static VerticalConfigurationGroup *OSDCC708Settings(PlaySettings *settings)
 {
     VerticalConfigurationGroup *grp =
         new VerticalConfigurationGroup(false, true, true, true);
     grp->setLabel(QObject::tr("ATSC Caption Settings"));
+    if (settings)
+        grp->setLabel(QObject::tr("Playback group settings for ") +
+                      settings->mGroupName + " - " +
+                      grp->getLabel());
 
 // default text zoom 1.0
-    grp->addChild(OSDCC708TextZoomPercentage());
+    grp->addChild(OSDCC708TextZoomPercentage(settings));
 
 // force X lines of captions
 // force caption character color
@@ -1764,17 +1906,17 @@
 // force background opacity
 
 // set default font type
-    grp->addChild(OSDCC708DefaultFontType());
+    grp->addChild(OSDCC708DefaultFontType(settings));
 
     return grp;
 }
 
-static HostComboBox *OSDCC708Font(
+static Setting *OSDCC708Font(
     const QString &subtype, const QString &subtypeName,
-    const QString &subtypeNameForHelp)
+    const QString &subtypeNameForHelp, PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox(
-        QString("OSDCC708%1Font").arg(subtype));
+    CREATE_COMBOBOX_SETTING(gc, QString("OSDCC708%1Font").arg(subtype),
+                            settings);
 
     gc->setLabel(subtypeName);
     QDir ttf(GetFontsDir(), GetFontsNameFilter());
@@ -1782,14 +1924,18 @@
     gc->setHelpText(
         QObject::tr("ATSC %1 closed caption font.").arg(subtypeNameForHelp));
 
-    return gc;
+    return wrap(gc, settings, (subtypeName.length() > 10));
 }
 
-static HorizontalConfigurationGroup *OSDCC708Fonts(void)
+static HorizontalConfigurationGroup *OSDCC708Fonts(PlaySettings *settings)
 {
     HorizontalConfigurationGroup *grpmain =
         new HorizontalConfigurationGroup(false, true, true, true);
     grpmain->setLabel(QObject::tr("ATSC Caption Fonts"));
+    if (settings)
+        grpmain->setLabel(QObject::tr("Playback group settings for ") +
+                          settings->mGroupName + " - " +
+                          grpmain->getLabel());
     VerticalConfigurationGroup *col[] =
     {
         new VerticalConfigurationGroup(false, false, true, true),
@@ -1825,16 +1971,18 @@
     for (uint j = 0; j < 7; ++j)
     {
         col[i]->addChild(OSDCC708Font(subtypes[i].arg(types[j]),
-                                      typeNames[j], typeNames[j]));
+                                      typeNames[j], typeNames[j],
+                                      settings));
     }
     grpmain->addChild(col[i]);
 
     i = 1;
     for (uint j = 0; j < 7; ++j)
     {
-        col[i]->addChild(OSDCC708Font(
-                             subtypes[i].arg(types[j]), "",
-                             QObject::tr("Italic") + ' ' + typeNames[j]));
+        col[i]->addChild(OSDCC708Font(subtypes[i].arg(types[j]),
+                                      (settings ? typeNames[j] : ""),
+                                      QObject::tr("Italic") + ' ' + typeNames[j],
+                                      settings));
     }
 
     grpmain->addChild(col[i]);
@@ -1842,9 +1990,9 @@
     return grpmain;
 }
 
-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();
@@ -1854,30 +2002,30 @@
         gc->addSelection(val, val, val.toLower() == "utf-8");
     }
 
-    return gc;
+    return wrap(gc, settings);
 }
 
-static HorizontalConfigurationGroup *ExternalSubtitleSettings()
+static HorizontalConfigurationGroup *ExternalSubtitleSettings(PlaySettings *settings)
 {
     HorizontalConfigurationGroup *grpmain =
         new HorizontalConfigurationGroup(false, true, true, true);
 
     grpmain->setLabel(QObject::tr("External Subtitle Settings"));
 
-    grpmain->addChild(SubtitleCodec());
+    grpmain->addChild(SubtitleCodec(settings));
 
     return grpmain;
 }
 
-static HostComboBox *OSDThemeFontSizeType()
+static Setting *OSDThemeFontSizeType(PlaySettings *settings)
 {
-    HostComboBox *gc = new HostComboBox("OSDThemeFontSizeType");
+    CREATE_COMBOBOX_SETTING(gc, "OSDThemeFontSizeType", settings);
     gc->setLabel(QObject::tr("Font size"));
     gc->addSelection(QObject::tr("default"), "default");
     gc->addSelection(QObject::tr("small"), "small");
     gc->addSelection(QObject::tr("big"), "big");
     gc->setHelpText(QObject::tr("default: TV, small: monitor, big:"));
-    return gc;
+    return wrap(gc, settings);
 }
 
 static HostComboBox *ChannelOrdering()
@@ -1889,44 +2037,48 @@
     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 *AlwaysStreamFiles()
@@ -1942,21 +2094,21 @@
     return gc;
 }
 
-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(
@@ -1964,12 +2116,12 @@
                         "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(
@@ -1977,36 +2129,36 @@
             "When enabled the new EIA-708 captions will be preferred over "
             "the old 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 LiveTV"));
     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(
@@ -2014,24 +2166,24 @@
             "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("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 "
@@ -2039,38 +2191,38 @@
                     "Saved\" and \"Bookmark Cleared\". If disabled, the "
                     "Select key will save the current position for each "
                     "keypress."));
-    return gc;
+    return wrap(gc, settings);
 }
 
 #if defined(USING_XV) || defined(USING_OPENGL_VIDEO) || defined(USING_VDPAU)
-static HostCheckBox *UsePicControls()
+static Setting *UsePicControls(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("UseOutputPictureControls");
+    CREATE_CHECKBOX_SETTING(gc, "UseOutputPictureControls", settings);
     gc->setLabel(QObject::tr("Enable picture controls"));
     gc->setValue(false);
     gc->setHelpText(
         QObject::tr(
             "If enabled, MythTV attempts to initialize picture controls "
             "(brightness, contrast, etc.) that are applied during playback."));
-    return gc;
+    return wrap(gc, settings);
 }
 #endif
 
-static HostLineEdit *UDPNotifyPort()
+static Setting *UDPNotifyPort(PlaySettings *settings)
 {
-    HostLineEdit *ge = new HostLineEdit("UDPNotifyPort");
+    CREATE_LINEEDIT_SETTING(ge, "UDPNotifyPort", settings);
     ge->setLabel(QObject::tr("UDP Notify Port"));
     ge->setValue("6948");
     ge->setHelpText(QObject::tr("During playback, MythTV will listen for "
                     "connections from the \"mythtvosd\" or \"mythudprelay\" "
                     "programs on this port.  See the README in "
                     "contrib/mythnotify/ for additional information."));
-    return ge;
+    return wrap(ge, 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");
@@ -2081,23 +2233,23 @@
                     "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 set, 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(
@@ -2106,12 +2258,12 @@
                         "'Watch Recording' screen when 'Jump to Program' "
                         "is activated. If set, 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(
@@ -2119,12 +2271,12 @@
                     "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 set, when you exit near the end of a "
@@ -2132,7 +2284,7 @@
                     "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()
@@ -2385,9 +2537,9 @@
     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));
@@ -2397,12 +2549,12 @@
             "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));
@@ -2410,12 +2562,12 @@
                         "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"));
     gc->addSelection(toString(kAdjustFill_AutoDetect_DefaultOff),
                      QString::number(kAdjustFill_AutoDetect_DefaultOff));
@@ -2426,7 +2578,7 @@
     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
@@ -2845,25 +2997,25 @@
     return gc;
 }
 
-ThemeSelector::ThemeSelector(QString label):
-    HostImageSelect(label) {
-
+static Setting *ThemeSelector(QString label, PlaySettings *settings=NULL)
+{
+    CREATE_IMAGESELECT_SETTING(gs, label, settings);
     ThemeType themetype = THEME_UI;
 
     if (label == "Theme")
     {
         themetype = THEME_UI;
-        setLabel(QObject::tr("UI Theme"));
+        gs->setLabel(QObject::tr("UI Theme"));
     }
     else if (label == "OSDTheme")
     {
         themetype = THEME_OSD;
-        setLabel(QObject::tr("OSD Theme"));
+        gs->setLabel(QObject::tr("OSD Theme"));
     }
     else if (label == "MenuTheme")
     {
         themetype = THEME_MENU;
-        setLabel(QObject::tr("Menu Theme"));
+        gs->setLabel(QObject::tr("Menu Theme"));
     }
 
     QDir themes(GetThemesParentDir());
@@ -2927,13 +3079,15 @@
             VERBOSE(VB_IMPORTANT, QString("Problem reading theme preview image"
                                           " %1").arg(preview.filePath()));
 
-        addImageSelection(name, previewImage, theme.fileName());
+        gs->addImageSelection(name, previewImage, theme.fileName());
     }
 
     if (themetype & THEME_UI)
-        setValue(DEFAULT_UI_THEME);
+        gs->setValue(DEFAULT_UI_THEME);
     else if (themetype & THEME_OSD)
-        setValue("BlackCurves-OSD");
+        gs->setValue("BlackCurves-OSD");
+
+    return wrap(gs, settings);
 }
 
 static HostComboBox *ChannelFormat()
@@ -3418,6 +3572,9 @@
 
         addTarget("6", group);
         addTarget("2", new VerticalConfigurationGroup(false, true));
+        QString dflt = getDefault(checkbox);
+        if (!dflt.isEmpty())
+            addTarget(dflt, group);
     }
 };
 
@@ -3431,6 +3588,9 @@
 
         addTarget("1", group);
         addTarget("0", new VerticalConfigurationGroup(false, true));
+        QString dflt = getDefault(checkbox);
+        if (!dflt.isEmpty())
+            addTarget(dflt, group);
     }
 };
 
@@ -3445,33 +3605,37 @@
 
         addTarget("1", setting);
         addTarget("0", new VerticalConfigurationGroup(false, false));
+        QString dflt = getDefault(checkbox);
+        if (!dflt.isEmpty())
+            addTarget(dflt, setting);
     }
 };
 
-static ConfigurationGroup *AudioSystemSettingsGroup()
+static ConfigurationGroup *AudioSystemSettingsGroup(PlaySettings *settings)
 {
     ConfigurationGroup *vcg = new VerticalConfigurationGroup(false, true, false, false);
 
     vcg->setLabel(QObject::tr("Audio System"));
     vcg->setUseLabel(false);
 
-    vcg->addChild(new AudioOutputDevice());
+    if (!settings)
+        vcg->addChild(new AudioOutputDevice());
 
-    Setting *numchannels = MaxAudioChannels();
+    Setting *numchannels = MaxAudioChannels(settings);
     vcg->addChild(numchannels);
 
     ConfigurationGroup *group1 =
         new VerticalConfigurationGroup(false, true, false, false);
 
-    group1->addChild(AudioUpmix());
-    group1->addChild(AudioUpmixType());
-    group1->addChild(PassThroughOutputDevice());
+    group1->addChild(AudioUpmix(settings));
+    group1->addChild(AudioUpmixType(settings));
+    group1->addChild(PassThroughOutputDevice(settings));
 
     ConfigurationGroup *settings1 =
         new HorizontalConfigurationGroup();
     settings1->setLabel(QObject::tr("Audio Processing Capabilities"));
-    settings1->addChild(AC3PassThrough());
-    settings1->addChild(DTSPassThrough());
+    settings1->addChild(AC3PassThrough(settings));
+    settings1->addChild(DTSPassThrough(settings));
 
     group1->addChild(settings1);
 
@@ -3480,7 +3644,7 @@
         new AudioSystemSurroundGroup(numchannels, group1);
     vcg->addChild(sub1);
 
-    Setting *advancedsettings = AdvancedAudioSettings();
+    Setting *advancedsettings = AdvancedAudioSettings(settings);
     vcg->addChild(advancedsettings);
 
     ConfigurationGroup *group2 =
@@ -3493,15 +3657,16 @@
     ConfigurationGroup *settings2 =
             new HorizontalConfigurationGroup(false, false, false, false);
 
-    Setting *srcqualityoverride = SRCQualityOverride();
+    Setting *srcqualityoverride = SRCQualityOverride(settings);
 
     AudioSystemAdvancedSettings *sub3 =
-        new AudioSystemAdvancedSettings(srcqualityoverride, SRCQuality());
+        new AudioSystemAdvancedSettings(srcqualityoverride,
+                                        SRCQuality(settings));
     settings2->addChild(srcqualityoverride);
     settings2->addChild(sub3);
 
     group2->addChild(settings2);
-    group2->addChild(AggressiveBuffer());
+    group2->addChild(AggressiveBuffer(settings));
 
     return vcg;
 
@@ -3510,23 +3675,23 @@
 class AudioMixerSettingsGroup : public TriggeredConfigurationGroup
 {
   public:
-    AudioMixerSettingsGroup() :
+    AudioMixerSettingsGroup(PlaySettings *psettings) :
         TriggeredConfigurationGroup(false, true, false, false)
     {
         setLabel(QObject::tr("Audio Mixer"));
         setUseLabel(false);
 
-        Setting *volumeControl = MythControlsVolume();
+        Setting *volumeControl = MythControlsVolume(psettings);
         addChild(volumeControl);
 
         // Mixer settings
         ConfigurationGroup *settings =
             new VerticalConfigurationGroup(false, true, false, false);
-        settings->addChild(MixerDevice());
-        settings->addChild(MixerControl());
-        settings->addChild(MixerVolume());
-        settings->addChild(PCMVolume());
-        settings->addChild(IndividualMuteControl());
+        settings->addChild(MixerDevice(psettings));
+        settings->addChild(MixerControl(psettings));
+        settings->addChild(MixerVolume(psettings));
+        settings->addChild(PCMVolume(psettings));
+        settings->addChild(IndividualMuteControl(psettings));
 
         ConfigurationGroup *dummy =
             new VerticalConfigurationGroup(false, true, false, false);
@@ -3535,6 +3700,9 @@
         setTrigger(volumeControl);
         addTarget("0", dummy);
         addTarget("1", settings);
+        QString dflt = getDefault(volumeControl);
+        if (!dflt.isEmpty())
+            addTarget(dflt, settings);
     }
 };
 
@@ -3608,16 +3776,16 @@
     return gs;
 }
 
-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()
@@ -3773,16 +3941,16 @@
 };
 
 #ifdef USING_OPENGL_VSYNC
-static HostCheckBox *UseOpenGLVSync()
+static Setting *UseOpenGLVSync(PlaySettings *settings)
 {
-    HostCheckBox *gc = new HostCheckBox("UseOpenGLVSync");
+    CREATE_CHECKBOX_SETTING(gc, "UseOpenGLVSync", settings);
     gc->setLabel(QObject::tr("Enable OpenGL vertical sync for timing"));
     gc->setValue(false);
     gc->setHelpText(QObject::tr(
                         "If it is supported by your hardware/drivers, "
                         "MythTV will use OpenGL vertical syncing for "
                         "video timing, reducing frame jitter."));
-    return gc;
+    return wrap(gc, settings);
 }
 #endif
 
@@ -4208,8 +4376,11 @@
     return gc;
 }
 
-MainGeneralSettings::MainGeneralSettings()
+MainGeneralSettings::MainGeneralSettings(PlaySettings *settings,
+                                         ConfigurationWizard *base)
 {
+    if (!settings)
+    {
     DatabaseSettings::addDatabaseSettings(this);
 
     VerticalConfigurationGroup *pin =
@@ -4218,11 +4389,22 @@
     pin->addChild(SetupPinCodeRequired());
     pin->addChild(SetupPinCode());
     addChild(pin);
+    }
 
-    addChild(AudioSystemSettingsGroup());
+    if (base)
+    {
+        base->addChild(AudioSystemSettingsGroup(settings));
+        base->addChild(new AudioMixerSettingsGroup(settings));
+    }
+    else
+    {
+        addChild(AudioSystemSettingsGroup(settings));
+        addChild(new AudioMixerSettingsGroup(settings));
+    }
 
-    addChild(new AudioMixerSettingsGroup());
 
+    if (!settings)
+    {
     VerticalConfigurationGroup *general =
         new VerticalConfigurationGroup(false, true, false, false);
     general->setLabel(QObject::tr("General"));
@@ -4262,54 +4444,72 @@
     remotecontrol->addChild(NetworkControlEnabled());
     remotecontrol->addChild(NetworkControlPort());
     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());
-    general1->addChild(AlwaysStreamFiles());
+    if (!settings)
+        general1->addChild(LiveTVIdleTimeout());
+    if (!settings)
+        general1->addChild(AlwaysStreamFiles());
 #ifdef USING_OPENGL_VSYNC
-    general1->addChild(UseOpenGLVSync());
+    general1->addChild(UseOpenGLVSync(settings));
 #endif // USING_OPENGL_VSYNC
 #if defined(USING_XV) || defined(USING_OPENGL_VIDEO) || defined(USING_VDPAU)
-    general1->addChild(UsePicControls());
+    general1->addChild(UsePicControls(settings));
 #endif // USING_XV
-    addChild(general1);
+    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);
@@ -4317,29 +4517,37 @@
         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));
@@ -4367,39 +4575,73 @@
     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());
     comms->addChild(CommSkipAllBlanks());
-    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());
 
@@ -4408,44 +4650,82 @@
     row->addChild(new MacDockSettings());
     row->addChild(new MacDesktopSettings());
     mac2->addChild(row);
+    }
 
-    addChild(mac2);
+    if (base)
+        base->addChild(mac2);
+    else
+        addChild(mac2);
 #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(new ThemeSelector("OSDTheme"));
-    osd->addChild(OSDGeneralTimeout());
-    osd->addChild(OSDProgramInfoTimeout());
-    osd->addChild(OSDFont());
-    osd->addChild(OSDThemeFontSizeType());
-    osd->addChild(EnableMHEG());
-    osd->addChild(PersistentBrowseMode());
-    osd->addChild(BrowseAllTuners());
-    addChild(osd);
+    osd->addChild(ThemeSelector("OSDTheme", settings));
+    osd->addChild(OSDGeneralTimeout(settings));
+    osd->addChild(OSDProgramInfoTimeout(settings));
+    osd->addChild(OSDFont(settings));
+    osd->addChild(OSDThemeFontSizeType(settings));
+    osd->addChild(EnableMHEG(settings));
+    if (!settings)
+    {
+    osd->addChild(PersistentBrowseMode(settings));
+    osd->addChild(BrowseAllTuners(settings));
+    }
+    if (base)
+        base->addChild(osd);
+    else
+        addChild(osd);
 
     VerticalConfigurationGroup *udp = new VerticalConfigurationGroup(false);
     udp->setLabel(QObject::tr("UDP OSD Notifications"));
-    udp->addChild(OSDNotifyTimeout());
-    udp->addChild(UDPNotifyPort());
-    addChild(udp);
+    if (settings)
+        udp->setLabel(QObject::tr("Playback group settings for ") +
+                      settings->mGroupName + " - " +
+                      udp->getLabel());
+    udp->addChild(OSDNotifyTimeout(settings));
+    udp->addChild(UDPNotifyPort(settings));
+    if (base)
+        base->addChild(udp);
+    else
+        addChild(udp);
 
     VerticalConfigurationGroup *cc = new VerticalConfigurationGroup(false);
     cc->setLabel(QObject::tr("Analog Closed Captions"));
-    cc->addChild(OSDCCFont());
+    if (settings)
+        cc->setLabel(QObject::tr("Playback group settings for ") +
+                     settings->mGroupName + " - " +
+                     cc->getLabel());
+    cc->addChild(OSDCCFont(settings));
     //cc->addChild(DecodeVBIFormat());
-    cc->addChild(CCBackground());
-    cc->addChild(DefaultCCMode());
-    cc->addChild(PreferCC708());
-    addChild(cc);
+    cc->addChild(CCBackground(settings));
+    cc->addChild(DefaultCCMode(settings));
+    cc->addChild(PreferCC708(settings));
+    if (base)
+        base->addChild(cc);
+    else
+        addChild(cc);
 
-    addChild(OSDCC708Settings());
-    addChild(OSDCC708Fonts());
-    addChild(ExternalSubtitleSettings());
+    if (base)
+    {
+        base->addChild(OSDCC708Settings(settings));
+        base->addChild(OSDCC708Fonts(settings));
+        base->addChild(ExternalSubtitleSettings(settings));
+    }
+    else
+    {
+        addChild(OSDCC708Settings(settings));
+        addChild(OSDCC708Fonts(settings));
+        addChild(ExternalSubtitleSettings(settings));
+    }
 
 #if CONFIG_DARWIN
     // Any Mac OS-specific OSD stuff would go here.
@@ -4597,7 +4877,7 @@
     VerticalConfigurationGroup* theme = new VerticalConfigurationGroup(false);
     theme->setLabel(QObject::tr("Theme"));
 
-    theme->addChild(new ThemeSelector("Theme"));
+    theme->addChild(ThemeSelector("Theme"));
 
     theme->addChild(ThemeCacheSize());
 
Index: programs/mythfrontend/main.cpp
===================================================================
--- programs/mythfrontend/main.cpp	(revision 24189)
+++ programs/mythfrontend/main.cpp	(working copy)
@@ -34,6 +34,7 @@
 #include "globalsettings.h"
 #include "profilegroup.h"
 #include "playgroup.h"
+#include "playsettings.h"
 #include "networkcontrol.h"
 #include "DVDRingBuffer.h"
 #include "scheduledrecording.h"
@@ -485,6 +486,27 @@
         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
+};
+
 void TVMenuCallback(void *data, QString &selection)
 {
     (void)data;
@@ -577,7 +599,8 @@
     }
     else if (sel == "settings playgroup")
     {
-        PlayGroupEditor editor;
+        PlayGroupEditor editor(pbgroupSetup,
+                               sizeof(pbgroupSetup)/sizeof(*pbgroupSetup));
         editor.exec();
     }
     else if (sel == "settings general")
@@ -749,6 +772,7 @@
                                               Qt::ISODate));
     pginfo->lenMins = lenMins;
     pginfo->isVideo = true;
+    pginfo->playgroup = "Videos";
     pginfo->pathname = mrl;
 
     QDir d(mrl + "/VIDEO_TS");
Index: programs/mythfrontend/globalsettings.h
===================================================================
--- programs/mythfrontend/globalsettings.h	(revision 24189)
+++ programs/mythfrontend/globalsettings.h	(working copy)
@@ -10,6 +10,7 @@
 #include "themeinfo.h"
 
 class QFileInfo;
+class PlaySettings;
 
 class AudioOutputDevice : public HostComboBox
 {
@@ -37,13 +38,15 @@
 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
@@ -67,7 +70,8 @@
 class MainGeneralSettings : public ConfigurationWizard
 {
   public:
-    MainGeneralSettings();
+    MainGeneralSettings(PlaySettings *settings=NULL,
+                        ConfigurationWizard *base=NULL);
 };
 
 class GeneralRecPrioritiesSettings : public ConfigurationWizard
@@ -155,7 +159,7 @@
     Q_OBJECT
 
   public:
-    PlaybackProfileConfigs(const QString &str);
+    PlaybackProfileConfigs(const QString &str, PlaySettings *settings);
     virtual ~PlaybackProfileConfigs();
 
   private:
@@ -167,7 +171,7 @@
 
   private:
     QStringList   profiles;
-    HostComboBox *grouptrigger;
+    ComboBoxSetting *grouptrigger;
 };
 
 #endif
Index: programs/mythtranscode/transcode.cpp
===================================================================
--- programs/mythtranscode/transcode.cpp	(revision 24189)
+++ programs/mythtranscode/transcode.cpp	(working copy)
@@ -36,10 +36,13 @@
 class AudioReencodeBuffer : public AudioOutput
 {
  public:
-    AudioReencodeBuffer(int audio_bits, int audio_channels)
+    AudioReencodeBuffer(int audio_bits, int audio_channels,
+                        PlaySettings *psettings)
+        : AudioOutput(psettings)
     {
         Reset();
-        const AudioSettings settings(audio_bits, audio_channels, 0, 0, false);
+        const AudioSettings settings(audio_bits, audio_channels, 0, 0, false,
+                                     psettings);
         Reconfigure(settings);
         bufsize = 512000;
         audiobuffer = new unsigned char[bufsize];
@@ -419,7 +422,8 @@
         statustime = statustime.addSecs(5);
     }
 
-    AudioOutput *audioOutput = new AudioReencodeBuffer(0, 0);
+    AudioOutput *audioOutput =
+        new AudioReencodeBuffer(0, 0, player_ctx->settings);
     AudioReencodeBuffer *arb = ((AudioReencodeBuffer*)audioOutput);
     nvp->SetAudioOutput(audioOutput);
     nvp->SetTranscoding(true);
Index: programs/mythavtest/main.cpp
===================================================================
--- programs/mythavtest/main.cpp	(revision 24189)
+++ programs/mythavtest/main.cpp	(working copy)
@@ -22,6 +22,7 @@
 #include "dbcheck.h"
 #include "myththemebase.h"
 #include "audiopulseutil.h"
+#include "playsettings.h"
 
 
 static void *run_priv_thread(void *data)
@@ -189,18 +190,6 @@
     if (pa_ret != GENERIC_EXIT_OK)
         return pa_ret;
 
-#if defined(Q_OS_MACX)
-    // Mac OS X doesn't define the AudioOutputDevice setting
-#else
-    QString auddevice = gContext->GetSetting("AudioOutputDevice");
-    if (auddevice.isEmpty())
-    {
-        VERBOSE(VB_IMPORTANT, "Fatal Error: Audio not configured, you need "
-                "to run 'mythfrontend', not 'mythtv'.");
-        return TV_EXIT_NO_AUDIO;
-    }
-#endif
-
     MythMainWindow *mainWindow = GetMythMainWindow();
     mainWindow->Init();
     gContext->SetMainWindow(mainWindow);
@@ -215,13 +204,6 @@
         return GENERIC_EXIT_DB_OUTOFDATE;
     }
 
-    TV *tv = new TV();
-    if (!tv->Init())
-    {
-        VERBOSE(VB_IMPORTANT, "Fatal Error: Could not initialize TV class.");
-        return TV_EXIT_NO_TV;
-    }
-
     ProgramInfo *pginfo = NULL;
 
     if (!filename.isEmpty() &&
@@ -240,6 +222,27 @@
 
     }
 
+    PlaySettings settings(pginfo->playgroup);
+
+#if defined(Q_OS_MACX)
+    // Mac OS X doesn't define the AudioOutputDevice setting
+#else
+    QString auddevice = settings.GetSetting("AudioOutputDevice", "");
+    if (auddevice.isEmpty())
+    {
+        VERBOSE(VB_IMPORTANT, "Fatal Error: Audio not configured, you need "
+                "to run 'mythfrontend', not 'mythtv'.");
+        return TV_EXIT_NO_AUDIO;
+    }
+#endif
+
+    TV *tv = new TV(&settings);
+    if (!tv->Init())
+    {
+        VERBOSE(VB_IMPORTANT, "Fatal Error: Could not initialize TV class.");
+        return TV_EXIT_NO_TV;
+    }
+
     TV::StartTV(pginfo, false);
 
     if (pginfo)
