Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 15506)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -19,6 +19,7 @@
 #include "programinfo.h"
 #include "channelutil.h"
 #include "videoouttypes.h"
+#include "channelutil.h"
 
 #include <qobject.h>
 
@@ -384,6 +385,11 @@
     void ToggleRecord(void);
     void BrowseChannel(const QString &channum);
 
+    uint    GetChanIDAnyTuner(const QString &chan);
+    void    GetNextProgramAnyTuner(int direction, InfoMap &infoMap);
+    QString GetProgramTunerStatus(InfoMap &infoMap);
+    uint    FindAvailableTuner(const QString &chanid);
+
     void DoTogglePictureAttribute(PictureAdjustType type);
     void DoChangePictureAttribute(
         PictureAdjustType type, PictureAttribute attr, bool up);
@@ -568,6 +574,8 @@
     QString browsechannum;
     QString browsechanid;
     QString browsestarttime;
+    bool browsealltuners;
+    DBChanList allchannels;   
 
     // Program Info for currently playing video
     // (or next video if InChangeState() is true)
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 15506)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -545,6 +545,7 @@
       browsemode(false), persistentbrowsemode(false),
       browseTimer(new QTimer(this)),
       browsechannum(""), browsechanid(""), browsestarttime(""),
+      browsealltuners(false),
       // Program Info for currently playing video
       recorderPlaybackInfo(NULL),
       playbackinfo(NULL), playbackLen(0),
@@ -634,6 +635,14 @@
         ff_rew_speeds.push_back(
             gContext->GetNumSetting(QString("FFRewSpeed%1").arg(i), def[i]));
 
+    browsealltuners = gContext->GetNumSetting("BrowseAllTuners", 0);
+    if (browsealltuners)
+    {
+        QString channelOrdering = gContext->GetSetting("ChannelOrdering", "channum");
+        allchannels = ChannelUtil::GetChannels(0, true, "channum, callsign");
+        ChannelUtil::SortChannels(allchannels, channelOrdering, true);
+    };
+
     vbimode = VBIMode::Parse(gContext->GetSetting("VbiFormat"));
 
     if (createWindow)
@@ -5611,6 +5620,125 @@
     return false;
 }
 
+uint TV::GetChanIDAnyTuner(const QString &chan)
+{
+    for (uint i = 0; i < allchannels.size(); ++i)
+        if (allchannels[i].channum == chan)
+            return allchannels[i].chanid;
+    return 0;
+};
+
+void TV::GetNextProgramAnyTuner(int direction, InfoMap &infoMap)
+{ 
+    uint chanid = infoMap["chanid"].toUInt();
+    if (infoMap["chanid"] == "")
+        chanid = GetChanIDAnyTuner(infoMap["channum"]);
+        
+    int chandir = -1;
+    switch(direction)
+    {
+        case BROWSE_UP:          chandir = CHANNEL_DIRECTION_UP;         break;
+        case BROWSE_DOWN:        chandir = CHANNEL_DIRECTION_DOWN;       break;
+        case BROWSE_FAVORITE:    chandir = CHANNEL_DIRECTION_FAVORITE;   break;
+    };
+    if (direction != -1)
+        chanid = ChannelUtil::GetNextChannel(allchannels, chanid, 0, chandir);
+
+    infoMap["chanid"] = QString("%1").arg(chanid);
+    infoMap["channum"] = ChannelUtil::GetChanNum(chanid);
+        
+
+    QDateTime nowtime = QDateTime::currentDateTime();
+    QDateTime latesttime = nowtime.addSecs(6*60*60);
+    QDateTime browsetime = QDateTime::fromString(infoMap["dbstarttime"], Qt::ISODate);
+
+    MSqlBindings bindings;
+    bindings[":CHANID"] = chanid;
+    bindings[":NOWTS"] = nowtime.toString("yyyy-MM-ddThh:mm:ss");
+    bindings[":LATESTTS"] = latesttime.toString("yyyy-MM-ddThh:mm:ss");
+    bindings[":BROWSETS"] = browsetime.toString("yyyy-MM-ddThh:mm:ss");
+
+    QString querystr = " WHERE program.chanid = :CHANID ";
+    switch(direction)
+    {
+        case BROWSE_LEFT:
+                querystr += " AND program.endtime <= :BROWSETS "
+                            " AND program.endtime > :NOWTS ";
+                break;
+
+        case BROWSE_RIGHT:
+                querystr += " AND program.starttime > :BROWSETS "
+                            " AND program.starttime < :LATESTTS ";
+                break;
+            
+        default:
+                querystr += " AND program.starttime <= :BROWSETS "
+                            " AND program.endtime > :BROWSETS ";
+    };
+
+    ProgramList progList;
+    progList.FromProgram(querystr, bindings);
+    
+    if (progList.isEmpty())
+    {
+        infoMap["dbstarttime"] = "";
+        return;
+    };
+
+    ProgramInfo* prog = (direction == BROWSE_LEFT) ? progList.last()
+                                                   : progList.first();
+    
+    infoMap["dbstarttime"] = prog->startts.toString(Qt::ISODate);
+}
+
+QString TV::GetProgramTunerStatus(InfoMap &infoMap)
+{
+    infoMap["tuner"] = infoMap["notuner"] = "";
+
+    uint cardid = FindAvailableTuner(infoMap["chanid"]);
+    
+    QString status;
+    if (!cardid)
+    {
+        infoMap["notuner"] = tr("No Tuner Available");
+        status = "unavailable";
+    }
+    else if (cardid == (uint)activerecorder->GetRecorderNumber())
+    {
+        infoMap["tuner"] = tr("Current Tuner");
+        status = "current";
+    }
+    else
+    {
+        infoMap["tuner"] = tr("Tuner")+QString(" %1").arg(cardid);
+        status = "available";
+    }
+    
+    return status;
+};
+
+uint TV::FindAvailableTuner(const QString &chanid)
+{
+    if (!activerecorder->ShouldSwitchToAnotherCard(chanid))
+        return activerecorder->GetRecorderNumber();
+
+    QStringList validlist = GetValidRecorderList(chanid.toUInt());
+    QStringList freelist = "GET_FREE_RECORDER_LIST";
+    if (!gContext->SendReceiveStringList(freelist, true))
+        return 0;
+
+    QStringList::iterator recIter;
+    for (recIter = validlist.begin(); recIter != validlist.end(); ++recIter)
+    {
+        if (freelist.find(*recIter) == freelist.end()) 
+            continue;
+
+        return (*recIter).toInt();
+    }
+
+    return 0;
+};
+
 void TV::EmbedOutput(WId wid, int x, int y, int w, int h)
 {
     embedWinID = wid;
@@ -6428,7 +6556,10 @@
     infoMap["channum"]     = browsechannum;
     infoMap["chanid"]      = browsechanid;
     
-    GetNextProgram(activerecorder, direction, infoMap);
+    if (browsealltuners)
+        GetNextProgramAnyTuner(direction, infoMap);
+    else
+        GetNextProgram(activerecorder, direction, infoMap);
     
     browsechannum = infoMap["channum"];
     browsechanid  = infoMap["chanid"];
@@ -6446,7 +6577,10 @@
     if (program_info)
         program_info->ToMap(infoMap);
 
+    QString tunerstatus = GetProgramTunerStatus(infoMap);
+    
     GetOSD()->ClearAllText("browse_info");
+    GetOSD()->SetFontFunction("browse_info", "tuner", tunerstatus);
     GetOSD()->SetText("browse_info", infoMap, -1);
 
     delete program_info;
@@ -6493,10 +6627,12 @@
             ProgramInfo::GetProgramAtDateTime(browsechanid, startts);
         program_info->ToggleRecord();
         program_info->ToMap(infoMap);
+        QString tunerstatus = GetProgramTunerStatus(infoMap);
 
         if (GetOSD())
         {
             GetOSD()->ClearAllText("browse_info");
+            GetOSD()->SetFontFunction("browse_info", "tuner", tunerstatus);
             GetOSD()->SetText("browse_info", infoMap, -1);
 
             if (activenvp == nvp)
@@ -6543,7 +6679,12 @@
 
 void TV::BrowseChannel(const QString &chan)
 {
-    if (!activerecorder->CheckChannel(chan))
+    if (browsealltuners)
+    {
+        if (!GetChanIDAnyTuner(chan))
+            return;
+    } 
+    else if (!activerecorder->CheckChannel(chan))
         return;
 
     browsechannum = chan;
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 15506)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -1792,6 +1792,18 @@
     return gc;
 }
 
+static HostCheckBox *BrowseAllTuners()
+{
+    HostCheckBox *gc = new HostCheckBox("BrowseAllTuners");
+    gc->setLabel(QObject::tr("Browse channels from all tuners"));
+    gc->setValue(true);
+    gc->setHelpText(QObject::tr("By default, browse mode only shows channels "
+                    "on the currently active tuner. If enabled, browse mode "
+                    "will shows all channels, no matter what tuner they "
+                    "exist on."));
+    return gc;
+}
+
 static HostCheckBox *AggressiveBuffer()
 {
     HostCheckBox *gc = new HostCheckBox("AggressiveSoundcardBuffer");
@@ -4562,6 +4574,7 @@
     osd->addChild(CCBackground());
     osd->addChild(DefaultCCMode());
     osd->addChild(PersistentBrowseMode());
+    osd->addChild(BrowseAllTuners());
     addChild(osd);
 
     addChild(OSDCC708Settings());

