All pastes #1658638 Raw Edit

Unnamed

public text v1 · immutable
#1658638 ·published 2009-11-05 19:51 UTC
rendered paste body
Index: libs/libmythtv/tvosdmenuentry.h
===================================================================
--- libs/libmythtv/tvosdmenuentry.h	(revision 22742)
+++ libs/libmythtv/tvosdmenuentry.h	(working copy)
@@ -63,7 +63,7 @@
         TVOSDMenuEntry* FindEntry(QString category);
 
     private:
-        void GetEntriesFromDB(void);
+        int GetEntriesFromDB(void);
         void InitDefaultEntries(void);
 
         QList<TVOSDMenuEntry*> curMenuEntries;
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 22742)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -839,45 +839,167 @@
       pseudoChangeChanTimerId(0),   speedChangeTimerId(0),
       errorRecoveryTimerId(0),      exitPlayerTimerId(0)
 {
-    VERBOSE(VB_PLAYBACK, LOC + "ctor");
+    VERBOSE(VB_PLAYBACK, LOC + "ctor -- begin");
 
     setObjectName("TV");
     keyRepeatTimer.start();
 
-    db_idle_timeout = gContext->GetNumSetting("LiveTVIdleTimeout", 0);
-    db_idle_timeout *= 60 * 1000; // convert from minutes to ms.
-    db_udpnotify_port      = gContext->GetNumSetting("UDPNotifyPort", 0);
-    db_browse_max_forward  = gContext->GetNumSetting("BrowseMaxForward",240)*60;
-    db_playback_exit_prompt= gContext->GetNumSetting("PlaybackExitPrompt", 0);
-    db_autoexpire_default  = gContext->GetNumSetting("AutoExpireDefault", 0);
+    QStringList keys;
+    QStringList values;
+    keys.push_back("LiveTVIdleTimeout");
+    values.push_back("0");
+    keys.push_back("UDPNotifyPort");
+    values.push_back("0");
+    keys.push_back("BrowseMaxForward");
+    values.push_back("240");
+    keys.push_back("PlaybackExitPrompt");
+    values.push_back("0");
+    keys.push_back("AutoExpireDefault");
+    values.push_back("0");
+    keys.push_back("AutomaticSetWatched");
+    values.push_back("0");
+    keys.push_back("EndOfRecordingExitPrompt");
+    values.push_back("0");
+    keys.push_back("JumpToProgramOSD");
+    values.push_back("1");
+    keys.push_back("GuiSizeForTV");
+    values.push_back("0");
+    keys.push_back("WatchTVGuide");
+    values.push_back("0");
+    keys.push_back("AltClearSavedPosition");
+    values.push_back("1");
+    keys.push_back("JobsRunOnRecordHost");
+    values.push_back("0");
+    keys.push_back("EnableDVDBookmark");
+    values.push_back("0");
+    keys.push_back("ContinueEmbeddedTVPlay");
+    values.push_back("0");
+    keys.push_back("UseFixedWindowSize");
+    values.push_back("1");
+    keys.push_back("PersistentBrowseMode");
+    values.push_back("0");
+    keys.push_back("BrowseAllTuners");
+    values.push_back("0");
+    keys.push_back("ChannelOrdering");
+    values.push_back("channum");
 
-    db_auto_set_watched     = gContext->GetNumSetting("AutomaticSetWatched", 0);
-    db_end_of_rec_exit_prompt =
-        gContext->GetNumSetting("EndOfRecordingExitPrompt", 0);
-    db_jump_prefer_osd     = gContext->GetNumSetting("JumpToProgramOSD", 1);
-    db_use_gui_size_for_tv = gContext->GetNumSetting("GuiSizeForTV", 0);
-    db_start_in_guide      = gContext->GetNumSetting("WatchTVGuide", 0);
-    db_toggle_bookmark     = gContext->GetNumSetting("AltClearSavedPosition",1);
-    db_run_jobs_on_remote  = gContext->GetNumSetting("JobsRunOnRecordHost", 0);
-    db_use_dvd_bookmark    = gContext->GetNumSetting("EnableDVDBookmark", 0);
-    db_continue_embedded   = gContext->GetNumSetting(
-        "ContinueEmbeddedTVPlay", 0);
-    db_use_fixed_size      = gContext->GetNumSettingOnHost(
-        "UseFixedWindowSize", gContext->GetHostName(), 1);
-    db_browse_always       = gContext->GetNumSetting("PersistentBrowseMode", 0);
-    db_browse_all_tuners   = gContext->GetNumSetting("BrowseAllTuners", 0);
+    keys.push_back("CustomFilters");
+    values.push_back("");
+    keys.push_back("ChannelFormat");
+    values.push_back("<num> <sign>");
+    keys.push_back("TimeFormat");
+    values.push_back("h:mm AP");
+    keys.push_back("ShortDateFormat");
+    values.push_back("M/d");
+    keys.push_back("SmartChannelChange");
+    values.push_back("0");
 
+    keys.push_back("IndividualMuteControl");
+    values.push_back("0");
+    keys.push_back("UseArrowAccels");
+    values.push_back("1");
+    keys.push_back("OSDGeneralTimeout");
+    values.push_back("2");
+    keys.push_back("OSDProgramInfoTimeout");
+    values.push_back("3");
+    keys.push_back("TryUnflaggedSkip");
+    values.push_back("0");
+
+    keys.push_back("ChannelGroupDefault");
+    values.push_back("-1");
+    keys.push_back("BrowseChannelGroup");
+    values.push_back("0");
+    keys.push_back("SmartForward");
+    values.push_back("0");
+    keys.push_back("StickyKeys");
+    values.push_back("0");
+    keys.push_back("FFRewReposTime");
+    values.push_back("100");
+    keys.push_back("FFRewReverse");
+    values.push_back("1");
+
+    keys.push_back("ChannelGroupDefault");
+    values.push_back("-1");
+    keys.push_back("BrowseChannelGroup");
+    values.push_back("0");
+    keys.push_back("VbiFormat");
+    values.push_back("");
+    keys.push_back("DecodeVBIFormat");
+    values.push_back("");
+
+    int ff_rew_def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
+    for (uint i = 0; i < sizeof(ff_rew_def)/sizeof(ff_rew_def[0]); i++)
+    {
+        keys.push_back(QString("FFRewSpeed%1").arg(i));
+        values.push_back(QString::number(ff_rew_def[i]));
+    }
+
+    QMap<QString,QString> map;
+    bool ok = MythDB::getMythDB()->GetSettings(
+        keys, values, MythDB::kCacheDefaults);
+
+    if (ok)
+    {
+        for (uint i = 0; i < (uint) keys.size(); i++)
+            map[keys[i]] = values[i];
+    }
+
+    // convert from minutes to ms.
+    db_idle_timeout        = map["LiveTVIdleTimeout"].toInt() * 60 * 1000;
+    db_udpnotify_port      = map["UDPNotifyPort"].toInt();
+    db_browse_max_forward  = map["BrowseMaxForward"].toInt() * 60;
+    db_playback_exit_prompt= map["PlaybackExitPrompt"].toInt();
+    db_autoexpire_default  = map["AutoExpireDefault"].toInt();
+    db_auto_set_watched    = map["AutomaticSetWatched"].toInt();
+    db_end_of_rec_exit_prompt = map["EndOfRecordingExitPrompt"].toInt();
+    db_jump_prefer_osd     = map["JumpToProgramOSD"].toInt();
+    db_use_gui_size_for_tv = map["GuiSizeForTV"].toInt();
+    db_start_in_guide      = map["WatchTVGuide"].toInt();
+    db_toggle_bookmark     = map["AltClearSavedPosition"].toInt();
+    db_run_jobs_on_remote  = map["JobsRunOnRecordHost"].toInt();
+    db_use_dvd_bookmark    = map["EnableDVDBookmark"].toInt();
+    db_continue_embedded   = map["ContinueEmbeddedTVPlay"].toInt();
+    db_use_fixed_size      = map["UseFixedWindowSize"].toInt();
+    db_browse_always       = map["PersistentBrowseMode"].toInt();
+    db_browse_all_tuners   = map["BrowseAllTuners"].toInt();
+    QString channelOrdering= map["ChannelOrdering"];
+    baseFilters           += map["CustomFilters"];
+    db_channel_format      = map["ChannelFormat"];
+    db_time_format         = map["TimeFormat"];
+    db_short_date_format   = map["ShortDateFormat"];
+    smartChannelChange     = map["SmartChannelChange"].toInt();
+    MuteIndividualChannels = map["IndividualMuteControl"].toInt();
+    arrowAccel             = map["UseArrowAccels"].toInt();
+    osd_general_timeout    = map["OSDGeneralTimeout"].toInt();
+    osd_prog_info_timeout  = map["OSDProgramInfoTimeout"].toInt();
+    tryUnflaggedSkip       = map["TryUnflaggedSkip"].toInt();
+    channel_group_id       = map["ChannelGroupDefault"].toInt();
+    browse_changrp         = map["BrowseChannelGroup"].toInt();
+    smartForward           = map["SmartForward"].toInt();
+    stickykeys             = map["StickyKeys"].toInt();
+    ff_rew_repos           = map["FFRewReposTime"].toFloat() * 0.01f;
+    ff_rew_reverse         = map["FFRewReverse"].toInt();
+    channel_group_id       = map["ChannelGroupDefault"].toInt();
+    browse_changrp         = map["BrowseChannelGroup"].toInt();
+    QString beVBI          = map["VbiFormat"];
+    QString feVBI          = map["DecodeVBIFormat"];
+
+    for (uint i = 0; i < sizeof(ff_rew_def)/sizeof(ff_rew_def[0]); i++)
+        ff_rew_speeds.push_back(map[QString("FFRewSpeed%1").arg(i)].toInt());
+
+    // process it..
+
     if (db_browse_all_tuners)
     {
         QMutexLocker locker(&browseLock);
-        QString channelOrdering = gContext->GetSetting(
-            "ChannelOrdering", "channum");
         db_browse_all_channels = ChannelUtil::GetChannels(
             0, true, "channum, callsign");
         ChannelUtil::SortChannels(
             db_browse_all_channels, channelOrdering, true);
     }
 
+    vbimode = VBIMode::Parse(!feVBI.isEmpty() ? feVBI : beVBI);
+
     sleep_times.push_back(SleepTimerInfo(QObject::tr("Off"),       0));
     sleep_times.push_back(SleepTimerInfo(QObject::tr("30m"),   30*60));
     sleep_times.push_back(SleepTimerInfo(QObject::tr("1h"),    60*60));
@@ -892,6 +1014,7 @@
     player.push_back(new PlayerContext("player"));
     playerActive = 0;
     playerLock.unlock();
+    VERBOSE(VB_PLAYBACK, LOC + "ctor -- end");
 }
 
 /** \fn TV::Init(bool)
@@ -902,6 +1025,8 @@
  */
 bool TV::Init(bool createWindow)
 {
+    VERBOSE(VB_PLAYBACK, LOC + "Init -- begin");
+
     MSqlQuery query(MSqlQuery::InitCon());
     if (!query.isConnected())
     {
@@ -910,35 +1035,6 @@
         return false;
     }
 
-    baseFilters         += gContext->GetSetting("CustomFilters");
-    db_channel_format    =gContext->GetSetting("ChannelFormat","<num> <sign>");
-    db_time_format       = gContext->GetSetting("TimeFormat", "h:mm AP");
-    db_short_date_format = gContext->GetSetting("ShortDateFormat", "M/d");
-    smartChannelChange   = gContext->GetNumSetting("SmartChannelChange", 0);
-    MuteIndividualChannels=gContext->GetNumSetting("IndividualMuteControl", 0);
-    arrowAccel           = gContext->GetNumSetting("UseArrowAccels", 1);
-    osd_general_timeout  = gContext->GetNumSetting("OSDGeneralTimeout", 2);
-    osd_prog_info_timeout= gContext->GetNumSetting("OSDProgramInfoTimeout", 3);
-    tryUnflaggedSkip     = gContext->GetNumSetting("TryUnflaggedSkip", 0);
-    channel_group_id     = gContext->GetNumSetting("ChannelGroupDefault", -1);
-    browse_changrp       = gContext->GetNumSetting("BrowseChannelGroup", 0);
-    smartForward         = gContext->GetNumSetting("SmartForward", 0);
-    stickykeys           = gContext->GetNumSetting("StickyKeys");
-    ff_rew_repos         = gContext->GetNumSetting("FFRewReposTime", 100)/100.0;
-    ff_rew_reverse       = gContext->GetNumSetting("FFRewReverse", 1);
-    int def[8] = { 3, 5, 10, 20, 30, 60, 120, 180 };
-    for (uint i = 0; i < sizeof(def)/sizeof(def[0]); i++)
-        ff_rew_speeds.push_back(
-            gContext->GetNumSetting(QString("FFRewSpeed%1").arg(i), def[i]));
-
-    vbimode = VBIMode::Parse(gContext->GetSetting("VbiFormat"));
-    QString feVBI = gContext->GetSetting("DecodeVBIFormat", "");
-    if (!feVBI.isEmpty())
-        vbimode = VBIMode::Parse(gContext->GetSetting(feVBI));
-
-    channel_group_id     = gContext->GetNumSetting("ChannelGroupDefault", -1);
-    browse_changrp       = gContext->GetNumSetting("BrowseChannelGroup", 0);
-
     if (browse_changrp && (channel_group_id > -1))
     {
       m_channellist = ChannelUtil::GetChannels(0, true, "channum, callsign", channel_group_id);
@@ -947,6 +1043,8 @@
 
     m_changrplist  = ChannelGroup::GetChannelGroups();
 
+    VERBOSE(VB_PLAYBACK, LOC + "Init -- end channel groups");
+
     if (createWindow)
     {
         bool fullscreen = !gContext->GetNumSetting("GuiSizeForTV", 0);
@@ -1040,6 +1138,7 @@
 
     mainLoopCondLock.unlock();
 
+    VERBOSE(VB_PLAYBACK, LOC + "Init -- end");
     return true;
 }
 
Index: libs/libmythtv/tvosdmenuentry.cpp
===================================================================
--- libs/libmythtv/tvosdmenuentry.cpp	(revision 22742)
+++ libs/libmythtv/tvosdmenuentry.cpp	(working copy)
@@ -238,54 +238,67 @@
     curMenuEntries.append(new TVOSDMenuEntry(
         "SLEEP",              1,  1,  1,  1, "Sleep"));
 
-    GetEntriesFromDB();
-    if (GetCount() != curMenuEntries.count())
+    int preload_cnt = curMenuEntries.size();
+    int loaded_cnt  = GetEntriesFromDB();
+    if (preload_cnt != loaded_cnt)
         UpdateDB();
 }
 
 int TVOSDMenuEntryList::GetCount(void)
 {
-    MSqlQuery query(MSqlQuery::InitCon());
-    if (!query.isConnected())
-        return curMenuEntries.count();
+    return (int) curMenuEntries.size();
+}
 
-    query.prepare ("SELECT COUNT(osdcategory) FROM tvosdmenu;");
-    if (query.exec() && query.isActive() && query.size() > 0)
+// Returns the number of entries intialized from database.
+int TVOSDMenuEntryList::GetEntriesFromDB(void)
+{
+    typedef QList<TVOSDMenuEntry*>::iterator Lit;
+    QMap<QString,Lit> catmap;
+    Lit it = curMenuEntries.begin();
+    QString catlist("");
+    for (; it != curMenuEntries.end(); ++it)
     {
-        query.next();
-        return query.value(0).toUInt();
+        QString cat = (*it)->GetCategory();
+        catlist += QString("'%1',").arg(cat);
+        catmap[cat] = it;
     }
 
-    MythDB::DBError(LOC + "GetCount()", query);
-    return 0;
-}
+    if (catlist.isEmpty())
+        return 0;
 
-void TVOSDMenuEntryList::GetEntriesFromDB(void)
-{
+    catlist = catlist.left(catlist.length() - 1);
     MSqlQuery query(MSqlQuery::InitCon());
-    if (!query.isConnected())
-        return;
+    query.prepare(
+        QString(
+            "SELECT osdcategory, livetv, recorded, video, dvd "
+            "FROM tvosdmenu "
+            "WHERE osdcategory IN (%1)").arg(catlist));
 
-    TVOSDMenuEntry *entry = NULL;
-    QString osdcategory;
-    QListIterator<TVOSDMenuEntry *> cm = GetIterator();
-    while (cm.hasNext())
+    if (!query.exec())
     {
-        entry = cm.next();
-        osdcategory = entry->GetCategory();
-        query.prepare("SELECT livetv, recorded, video, dvd "
-                    "FROM tvosdmenu WHERE osdcategory = :OSDCATEGORY;");
-        query.bindValue(":OSDCATEGORY", osdcategory);
+        MythDB::DBError("TVOSDMenuEntryList::GetEntriesFromDB()", query);
+        return 0;
+    }
 
-        if (query.exec() && query.isActive() && query.size() == 1)
+    int cnt = 0;
+    while (query.next())
+    {
+        QString cat = query.value(0).toString();
+        QMap<QString,Lit>::iterator mit = catmap.find(cat);
+        if (mit == catmap.end())
         {
-            query.next();
-            entry->UpdateEntry(query.value(0).toInt(),
-                               query.value(1).toInt(),
-                               query.value(2).toInt(),
-                               query.value(3).toInt());
+            VERBOSE(VB_IMPORTANT, QString("TVOSDMenuEntryList, Error: ") +
+                    QString("Unable to find category '%1'").arg(cat));
+            continue;
         }
+
+        (**mit)->UpdateEntry(query.value(1).toInt(),
+                             query.value(2).toInt(),
+                             query.value(3).toInt(),
+                             query.value(4).toInt());
+        cnt++;
     }
+    return cnt;
 }
 
 void TVOSDMenuEntryList::UpdateDB(void)
Index: libs/libmythtv/videoout_xv.h
===================================================================
--- libs/libmythtv/videoout_xv.h	(revision 22742)
+++ libs/libmythtv/videoout_xv.h	(working copy)
@@ -209,6 +209,7 @@
     int                  non_xv_fps;
     PixelFormat          non_xv_av_format;
     time_t               non_xv_stop_time;
+    bool                 first_show;
 
     // Basic XvMC drawing info
     XvMCBufferSettings  *xvmc_buf_attr;
Index: libs/libmythtv/videoout_xv.cpp
===================================================================
--- libs/libmythtv/videoout_xv.cpp	(revision 22742)
+++ libs/libmythtv/videoout_xv.cpp	(working copy)
@@ -114,6 +114,7 @@
 
       XJ_non_xv_image(0), non_xv_frames_shown(0), non_xv_show_frame(1),
       non_xv_fps(0), non_xv_av_format(PIX_FMT_NB), non_xv_stop_time(0),
+      first_show(true),
 
       xvmc_buf_attr(new XvMCBufferSettings()),
       xvmc_chroma(XVMC_CHROMA_FORMAT_420), xvmc_ctx(NULL),
@@ -2464,6 +2465,12 @@
 // this is documented in videooutbase.cpp
 void VideoOutputXv::Show(FrameScanType scan)
 {
+    if (first_show)
+    {
+        VERBOSE(VB_IMPORTANT, LOC + "First Show");
+        first_show = false;
+    }
+
     if (IsErrored())
     {
         VERBOSE(VB_IMPORTANT, LOC_ERR + "IsErrored() is true in Show()");
Index: libs/libmyth/mythcontext.h
===================================================================
--- libs/libmyth/mythcontext.h	(revision 22742)
+++ libs/libmyth/mythcontext.h	(working copy)
@@ -114,7 +114,7 @@
 
     QString GetHostName(void);
 
-    void ClearSettingsCache(QString myKey = "", QString newVal = "");
+    void ClearSettingsCache(const QString &myKey = QString(""));
     void ActivateSettingsCache(bool activate = true);
     void OverrideSettingForSession(const QString &key, const QString &newValue);
 
Index: libs/libmyth/mythcontext.cpp
===================================================================
--- libs/libmyth/mythcontext.cpp	(revision 22742)
+++ libs/libmyth/mythcontext.cpp	(working copy)
@@ -1895,9 +1895,9 @@
     return ret;
 }
 
-void MythContext::ClearSettingsCache(QString myKey, QString newVal)
+void MythContext::ClearSettingsCache(const QString &myKey)
 {
-    d->m_database->ClearSettingsCache(myKey, newVal);
+    d->m_database->ClearSettingsCache(myKey);
 }
 
 void MythContext::ActivateSettingsCache(bool activate)
Index: libs/libmythdb/mythdb.cpp
===================================================================
--- libs/libmythdb/mythdb.cpp	(revision 22742)
+++ libs/libmythdb/mythdb.cpp	(working copy)
@@ -1,4 +1,8 @@
+#include <vector>
+using namespace std;
+
 #include <QMutex>
+#include <QReadWriteLock>
 #include <QHash>
 #include <QSqlError>
 
@@ -44,6 +48,7 @@
     MythDB::destroyMythDB();
 }
 
+typedef QHash<QString,QString> SettingsMap;
 
 class MythDBPrivate
 {
@@ -58,18 +63,21 @@
     Settings *m_settings;
 
     bool ignoreDatabase;
-    bool useSettingsCache;
     bool suppressDBMessages;
-    QMutex settingsCacheLock;
-    QHash <QString, QString> settingsCache;      // permanent settings in the DB
-    QHash <QString, QString> overriddenSettings; // overridden this session only
+
+    QReadWriteLock settingsCacheLock;
+    volatile bool useSettingsCache;
+    /// Permanent settings in the DB and overridden settings
+    SettingsMap settingsCache;
+    /// Overridden this session only
+    SettingsMap overriddenSettings;
 };
 
 static const int settings_reserve = 61;
 
 MythDBPrivate::MythDBPrivate()
     : m_settings(new Settings()),
-      ignoreDatabase(false), useSettingsCache(false), suppressDBMessages(true)
+      ignoreDatabase(false), suppressDBMessages(true), useSettingsCache(false)
 {
     m_localhostname.clear();
     settingsCache.reserve(settings_reserve);
@@ -174,15 +182,18 @@
     d->m_DBparams = params;
 }
 
-void MythDB::SetLocalHostname(QString name)
+void MythDB::SetLocalHostname(const QString &name)
 {
-    d->m_localhostname = name;
+    if (d->m_localhostname != name.toLower())
+    {
+        d->m_localhostname = name.toLower();
+        ClearSettingsCache();
+    }
 }
 
 QString MythDB::GetHostName(void)
 {
-    QString tmp = d->m_localhostname;
-    return tmp;
+    return d->m_localhostname;
 }
 
 void MythDB::IgnoreDatabase(bool bIgnore)
@@ -218,16 +229,16 @@
 }
 
 bool MythDB::SaveSettingOnHost(const QString &key,
-                                    const QString &newValue,
-                                    const QString &host)
+                               const QString &newValue,
+                               const QString &host)
 {
     QString LOC  = QString("SaveSettingOnHost('%1') ").arg(key);
     bool success = false;
 
     if (d->ignoreDatabase)
     {
-        ClearSettingsCache(key, newValue);
-        ClearSettingsCache(host + ' ' + key, newValue);
+        if (host.toLower() == d->m_localhostname)
+            OverrideSettingForSession(key, newValue);
         return true;
     }
 
@@ -284,86 +295,223 @@
         VERBOSE(VB_IMPORTANT, LOC + "- database not open");
     }
 
-    ClearSettingsCache(key, newValue);
-    ClearSettingsCache(host + ' ' + key, newValue);
+    ClearSettingsCache(host + ' ' + key);
 
     return success;
 }
 
-QString MythDB::GetSetting(const QString &key, const QString &defaultval)
+QString MythDB::GetSetting(const QString &_key, const QString &defaultval)
 {
+    QString key = _key.toLower();
     QString value;
 
-    if (d->overriddenSettings.contains(key))
+    d->settingsCacheLock.lockForRead();
+    if (d->useSettingsCache)
     {
-        value = d->overriddenSettings[key];
+        SettingsMap::const_iterator it = d->settingsCache.find(key);
+        if (it != d->settingsCache.end())
+        {
+            value = *it;
+            d->settingsCacheLock.unlock();
+            return value;
+        }
+    }
+    else
+    {
+        SettingsMap::const_iterator it = d->overriddenSettings.find(key);
+        if (it != d->overriddenSettings.end())
+        {
+            value = *it;
+            d->settingsCacheLock.unlock();
+            return value;
+        }
+    }
+    d->settingsCacheLock.unlock();
+
+    if (d->ignoreDatabase)
         return value;
+
+    MSqlQuery query(MSqlQuery::InitCon());
+    if (!query.isConnected())
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("Database not open while trying to load setting: %1")
+                .arg(key));
+        return d->m_settings->GetSetting(key, defaultval);
     }
 
-    d->settingsCacheLock.lock();
+    query.prepare(
+        "SELECT data "
+        "FROM settings "
+        "WHERE value = :KEY AND hostname = :HOSTNAME");
+    query.bindValue(":KEY", key);
+    query.bindValue(":HOSTNAME", d->m_localhostname);
+    
+    if (query.exec() && query.next())
+    {
+        value = query.value(0).toString();
+    }
+    else
+    {
+        query.prepare(
+            "SELECT data "
+            "FROM settings "
+            "WHERE value = :KEY AND hostname IS NULL");
+        query.bindValue(":KEY", key);
 
-    value = d->settingsCache.value(key, "_cold_");
+        if (query.exec() && query.next())
+        {
+            value = query.value(0).toString();
+        }
+        else
+        {
+            return d->m_settings->GetSetting(key, defaultval);
+        }
+    }
 
-    d->settingsCacheLock.unlock();
+    if (d->useSettingsCache)
+    {
+        key.squeeze();
+        value.squeeze();
+        d->settingsCacheLock.lockForWrite();
+        // another thread may have inserted a value into the cache
+        // while we did not have the lock, check first then save
+        if (d->settingsCache.find(key) == d->settingsCache.end())
+            d->settingsCache[key] = value;
+        d->settingsCacheLock.unlock();
+    }
 
-    if (value != "_cold_" && d->useSettingsCache)
-        return value;
+    return value;
+}
 
-    bool found = false;
-    if (!d->ignoreDatabase)
+bool MythDB::GetSettings(
+    const QStringList &_keys, QStringList &values, CacheBehavior cb)
+{
+    if (_keys.size() != values.size())
+        return false;
+
+    uint done_cnt = 0;
+    vector<bool> done;
+    done.resize(_keys.size(), false);
+
+    QStringList keys;
+    for (uint i = 0; i < (uint) _keys.size(); ++i)
+        keys.push_back(_keys[i].toLower());
+
+    d->settingsCacheLock.lockForRead();
+    if (d->useSettingsCache)
     {
-        MSqlQuery query(MSqlQuery::InitCon());
-        if (query.isConnected())
+        for (uint i = 0; i < (uint) keys.size(); ++i)
         {
-            query.prepare("SELECT data FROM settings WHERE value "
-                          "= :KEY AND hostname = :HOSTNAME ;");
-            query.bindValue(":KEY", key);
-            query.bindValue(":HOSTNAME", d->m_localhostname);
-
-            if (query.exec() && query.next())
+            SettingsMap::const_iterator it = d->settingsCache.find(keys[i]);
+            if (it != d->settingsCache.end())
             {
-                found = true;
-                value = query.value(0).toString();
+                values[i] = *it;
+                done[i] = true;
+                done_cnt++;
             }
-            else
+        }
+    }
+    else
+    {
+        for (uint i = 0; i < (uint) keys.size(); ++i)
+        {
+            SettingsMap::const_iterator it = d->overriddenSettings.find(keys[i]);
+            if (it != d->overriddenSettings.end())
             {
-                query.prepare("SELECT data FROM settings "
-                              "WHERE value = :KEY AND "
-                              "hostname IS NULL;");
-                query.bindValue(":KEY", key);
-
-                if (query.exec() && query.next())
-                {
-                    found = true;
-                    value = query.value(0).toString();
-                }
-                else
-                {
-                    value = defaultval;
-                }
+                values[i] = *it;
+                done[i] = true;
+                done_cnt++;
             }
         }
+    }
+    d->settingsCacheLock.unlock();
+
+    if (done.size() == done_cnt || d->ignoreDatabase)
+        return true;
+
+    QString keylist("");
+    QMap<QString,int> keymap;
+    for (uint i = 0; i < (uint) keys.size(); ++i)
+    {
+        if (done[i])
+            continue;
+
+        QString key = keys[i];
+        if (!key.contains("'"))
+        {
+            keylist += QString("'%1',").arg(key);
+            keymap[key] = i;
+        }
         else
+        { // don't bother optimizing this case..
+            values[i] = GetSetting(key, values[i]);
+            done[i] = true;
+            done_cnt++;
+        }
+    }
+
+    if (keylist.isEmpty())
+        return true;
+
+    keylist = keylist.left(keylist.length() - 1);
+
+    MSqlQuery query(MSqlQuery::InitCon());
+    if (!query.exec(
+            QString(
+                "SELECT value, data, hostname "
+                "FROM settings "
+                "WHERE (hostname = '%1' OR hostname IS NULL) AND "
+                "      value IN (%2) "
+                "ORDER BY hostname DESC")
+            .arg(d->m_localhostname).arg(keylist)))
+    {
+        DBError("GetSettings", query);
+        return false;
+    }
+
+    while (query.next())
+    {
+        QString key = query.value(0).toString().toLower();
+        QMap<QString,int>::const_iterator it = keymap.find(key);
+        if (it != keymap.end() && !done[*it])
         {
-            VERBOSE(VB_IMPORTANT,
-                    QString("Database not open while trying to "
-                            "load setting: %1")
-                    .arg(key));
+            values[*it] = query.value(1).toString();
+            done[*it] = true;
+            done_cnt++;
         }
     }
 
-    if (!found)
-        return d->m_settings->GetSetting(key, defaultval);
+    if (d->useSettingsCache)
+    {
+        VERBOSE(VB_IMPORTANT, "d->useSettingsCache");
+        d->settingsCacheLock.lockForWrite();
+        QMap<QString,int>::const_iterator it = keymap.begin();
+        for (; it != keymap.end(); ++it)
+        {
+            if ((kCacheDBOnly == cb) && !done[*it])
+            {
+                VERBOSE(VB_IMPORTANT, QString("Not caching '%1'").arg(it.key()));
+                continue;
+            }
 
-    // Do not store default values since they may not have been specified.
-    if (!value.isNull() && d->useSettingsCache)
-    {
-        d->settingsCacheLock.lock();
-        d->settingsCache[key] = value;
+            QString key = it.key(), value = values[*it];
+
+            // another thread may have inserted a value into the cache
+            // while we did not have the lock, check first then save
+            if (d->settingsCache.find(key) == d->settingsCache.end())
+            {
+                key.squeeze();
+                value.squeeze();
+                d->settingsCache[key] = value;
+            }
+        }
         d->settingsCacheLock.unlock();
     }
+    else
+        VERBOSE(VB_IMPORTANT, "!d->useSettingsCache");
 
-    return value;
+    return true;
 }
 
 int MythDB::GetNumSetting(const QString &key, int defaultval)
@@ -382,74 +530,71 @@
     return retval.toDouble();
 }
 
-QString MythDB::GetSettingOnHost(const QString &key, const QString &host,
-                                      const QString &defaultval)
+QString MythDB::GetSettingOnHost(const QString &_key, const QString &_host,
+                                 const QString &defaultval)
 {
-    bool found = false;
+    QString key   = _key.toLower();
+    QString host  = _host.toLower();
     QString value = defaultval;
     QString myKey = host + ' ' + key;
 
-    if (d->overriddenSettings.contains(myKey))
+    d->settingsCacheLock.lockForRead();
+    if (d->useSettingsCache)
     {
-        value = d->overriddenSettings[myKey];
-        return value;
+        SettingsMap::const_iterator it = d->settingsCache.find(myKey);
+        if (it != d->settingsCache.end())
+        {
+            value = *it;
+            d->settingsCacheLock.unlock();
+            return value;
+        }
     }
-
-    if ((host == d->m_localhostname) &&
-        (d->overriddenSettings.contains(key)))
+    else
     {
-
-        value = d->overriddenSettings[key];
-        return value;
-    }
-
-    if (d->useSettingsCache)
-    {
-        d->settingsCacheLock.lock();
-        if (d->settingsCache.contains(myKey))
+        SettingsMap::const_iterator it = d->overriddenSettings.find(myKey);
+        if (it != d->overriddenSettings.end())
         {
-            value = d->settingsCache[myKey];
+            value = *it;
             d->settingsCacheLock.unlock();
             return value;
         }
-        d->settingsCacheLock.unlock();
     }
+    d->settingsCacheLock.unlock();
 
-    if (!d->ignoreDatabase)
+    if (d->ignoreDatabase)
+        return value;
+
+    MSqlQuery query(MSqlQuery::InitCon());
+    if (!query.isConnected())
     {
-        MSqlQuery query(MSqlQuery::InitCon());
-        if (query.isConnected())
-        {
-            query.prepare("SELECT data FROM settings WHERE value = :VALUE "
-                          "AND hostname = :HOSTNAME ;");
-            query.bindValue(":VALUE", key);
-            query.bindValue(":HOSTNAME", host);
+        VERBOSE(VB_IMPORTANT,
+                QString("Database not open while trying to "
+                        "load setting: %1").arg(key));
+        return value;
+    }
 
-            if (query.exec() && query.isActive() && query.size() > 0)
-            {
-                if (query.next())
-                {
-                    value = query.value(0).toString();
-                    found = true;
-                }
-            }
-        }
-        else
+    query.prepare(
+        "SELECT data "
+        "FROM settings "
+        "WHERE value = :VALUE AND hostname = :HOSTNAME");
+    query.bindValue(":VALUE", key);
+    query.bindValue(":HOSTNAME", host);
+
+    if (query.exec() && query.next())
+    {
+        value = query.value(0).toString();
+
+        if (d->useSettingsCache)
         {
-            VERBOSE(VB_IMPORTANT,
-                    QString("Database not open while trying to "
-                            "load setting: %1")
-                    .arg(key));
+            myKey.squeeze();
+            value.squeeze();
+            d->settingsCacheLock.lockForWrite();
+            if (d->settingsCache.find(myKey) == d->settingsCache.end())
+                d->settingsCache[myKey] = value;
+            d->settingsCacheLock.unlock();
         }
     }
 
-    if (found && d->useSettingsCache)
-    {
-        d->settingsCacheLock.lock();
-        d->settingsCache[host + ' ' + key] = value;
-        d->settingsCacheLock.unlock();
-    }
-
     return value;
 }
 
@@ -474,7 +619,7 @@
 void MythDB::SetSetting(const QString &key, const QString &newValue)
 {
     d->m_settings->SetSetting(key, newValue);
-    ClearSettingsCache(key, newValue);
+    ClearSettingsCache(key);
 }
 
 void MythDB::GetResolutionSetting(const QString &type,
@@ -550,28 +695,75 @@
  * This allows defining settings for the session only, without touching the
  * settings in the data base.
  */
-void MythDB::OverrideSettingForSession(const QString &key,
-                                            const QString &value)
+void MythDB::OverrideSettingForSession(
+    const QString &key, const QString &value)
 {
-    d->overriddenSettings[key] = value;
+    QString mk = key.toLower(), mk2 = d->m_localhostname + ' ' + mk, mv = value;
+    mk.squeeze();
+    mk2.squeeze();
+    mv.squeeze();
+
+    d->settingsCacheLock.lockForWrite();
+    d->overriddenSettings[mk] = mv;
+    d->settingsCache[mk]      = mv;
+    d->settingsCache[mk2]     = mv;
+    d->settingsCacheLock.unlock();
 }
 
-void MythDB::ClearSettingsCache(QString myKey, QString newVal)
+static void clear(
+    SettingsMap &cache, SettingsMap &overrides, const QString &myKey)
 {
-    d->settingsCacheLock.lock();
-    if (!myKey.isEmpty() && d->settingsCache.contains(myKey))
+    // Do the actual clearing..
+    SettingsMap::iterator it = cache.find(myKey);
+    if (it != cache.end())
     {
-        VERBOSE(VB_DATABASE, QString("Clearing Settings Cache for '%1'.")
-                                    .arg(myKey));
-        d->settingsCache.remove(myKey);
-        d->settingsCache[myKey] = newVal;
+        SettingsMap::const_iterator oit = overrides.find(myKey);
+        if (oit == overrides.end())
+        {
+            VERBOSE(VB_DATABASE,
+                    QString("Clearing Settings Cache for '%1'.").arg(myKey));
+            cache.erase(it);
+        }
+        else
+        {
+            VERBOSE(VB_DATABASE,
+                    QString("Clearing Cache of overridden '%1' ignored.")
+                    .arg(myKey));
+        }
     }
-    else
+}
+
+void MythDB::ClearSettingsCache(const QString &_key)
+{
+    d->settingsCacheLock.lockForWrite();
+
+    if (_key.isEmpty())
     {
         VERBOSE(VB_DATABASE, "Clearing Settings Cache.");
         d->settingsCache.clear();
         d->settingsCache.reserve(settings_reserve);
+
+        SettingsMap::const_iterator it = d->overriddenSettings.begin();
+        for (; it != d->overriddenSettings.end(); ++it)
+        {
+            QString mk2 = d->m_localhostname + ' ' + it.key();
+            mk2.squeeze();
+
+            d->settingsCache[it.key()] = *it;
+            d->settingsCache[mk2] = *it;
+        }
     }
+    else
+    {
+        QString myKey = _key.toLower();
+        clear(d->settingsCache, d->overriddenSettings, myKey);
+
+        // To be safe always clear any local[ized] version too
+        QStringList mkl = myKey.split(QChar(' '));
+        if (mkl.size() == 2)
+            clear(d->settingsCache, d->overriddenSettings, mkl[1]);        
+    }
+
     d->settingsCacheLock.unlock();
 }
 
@@ -585,4 +777,3 @@
     d->useSettingsCache = activate;
     ClearSettingsCache();
 }
-
Index: libs/libmythdb/mythdb.h
===================================================================
--- libs/libmythdb/mythdb.h	(revision 22742)
+++ libs/libmythdb/mythdb.h	(working copy)
@@ -13,6 +13,11 @@
 class MPUBLIC MythDB
 {
   public:
+    typedef enum
+    {
+        kCacheDBOnly,
+        kCacheDefaults,
+    } CacheBehavior;
 
     MDBManager *GetDBManager(void);
     Settings *GetOldSettings(void);
@@ -23,7 +28,7 @@
     DatabaseParams GetDatabaseParams(void);
     void SetDatabaseParams(const DatabaseParams &params);
 
-    void SetLocalHostname(QString name);
+    void SetLocalHostname(const QString &name);
     QString GetHostName(void);
 
     void IgnoreDatabase(bool bIgnore);
@@ -32,7 +37,7 @@
     void SetSuppressDBMessages(bool bUpgraded);
     bool SuppressDBMessages(void) const;
 
-    void ClearSettingsCache(QString myKey = "", QString newVal = "");
+    void ClearSettingsCache(const QString &key = QString());
     void ActivateSettingsCache(bool activate = true);
     void OverrideSettingForSession(const QString &key, const QString &newValue);
 
@@ -42,6 +47,9 @@
                            const QString &host);
 
     QString GetSetting(const QString &key, const QString &defaultval = "");
+    bool GetSettings(const QStringList &_keys, QStringList &values,
+                     CacheBehavior cb = kCacheDBOnly);
+
     int GetNumSetting(const QString &key, int defaultval = 0);
     double GetFloatSetting(const QString &key, double defaultval = 0.0);
     void GetResolutionSetting(const QString &type, int &width, int &height,