Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 19464)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -250,7 +250,7 @@
                             bool isDVD, bool isDVDStillFrame);
 
     void GetNextProgram(RemoteEncoder *enc, int direction,
-                        InfoMap &infoMap);
+                        InfoMap &infoMap) const;
 
     // static functions
     static void InitKeys(void);
@@ -494,6 +494,11 @@
 
     void ToggleRecord(PlayerContext*);
 
+    uint    GetChanIDAnyTuner(const QString &chan) const;
+    QString GetChanNumAnyTuner(const uint &chanid) const;
+    void    GetNextProgramAnyTuner(int direction, InfoMap &infoMap,
+                                   ProgramInfo *prog) const;
+
     void DoTogglePictureAttribute(const PlayerContext*,
                                   PictureAdjustType type);
     void DoChangePictureAttribute(
@@ -682,6 +687,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 19464)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -654,6 +654,7 @@
       // channel browsing state variables
       browsemode(false), persistentbrowsemode(false),
       browsechannum(""), browsechanid(""), browsestarttime(""),
+      browsealltuners(false),
       // Program Info for currently playing video
       lastProgram(NULL),
       inPlaylist(false), underNetworkControl(false),
@@ -759,6 +760,15 @@
         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"));
     QString feVBI = gContext->GetSetting("DecodeVBIFormat", "");
     if (!feVBI.isEmpty())
@@ -7135,7 +7145,7 @@
  *  \param infoMap InfoMap to fill in with returned data
  */
 void TV::GetNextProgram(RemoteEncoder *enc, int direction,
-                        InfoMap &infoMap)
+                        InfoMap &infoMap) const
 {
     QString title, subtitle, desc, category, endtime, callsign, iconpath;
     QDateTime begts, endts;
@@ -7146,7 +7156,7 @@
     QString seriesid  = infoMap["seriesid"];
     QString programid = infoMap["programid"];
 
-    PlayerContext *actx = NULL;
+    const PlayerContext *actx = NULL;
     if (!enc)
     {
         actx = GetPlayerReadLock(-1, __FILE__, __LINE__);
@@ -7354,6 +7364,91 @@
     embedCheckTimerId = 0;
 }
 
+uint TV::GetChanIDAnyTuner(const QString &chan) const
+{
+    for (uint i = 0; i < allchannels.size(); ++i)
+    {
+        if (allchannels[i].channum == chan)
+            return allchannels[i].chanid;
+    }
+    return 0;
+}
+
+QString TV::GetChanNumAnyTuner(const uint &chanid) const
+{
+    for (uint i = 0; i < allchannels.size(); ++i)
+    {
+        if (allchannels[i].chanid == chanid)
+            return allchannels[i].channum;
+    }
+    return "";
+}
+
+void TV::GetNextProgramAnyTuner(int direction, InfoMap &infoMap,
+                                ProgramInfo *prog) const
+{
+    uint chanid = infoMap["chanid"].toUInt();
+    if (!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"] = GetChanNumAnyTuner(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");
+    bindings[":BROWSETS2"] = 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 > :BROWSETS2 ";
+    };
+
+    ProgramList progList;
+    progList.FromProgram(querystr, bindings);
+    
+    if (progList.isEmpty())
+    {
+        infoMap["dbstarttime"] = "";
+        return;
+    }
+
+    prog = (direction == BROWSE_LEFT) ?
+        progList[progList.size() - 1] : progList[0];
+
+    infoMap["dbstarttime"] = prog->startts.toString(Qt::ISODate);
+}
+
 void TV::DrawUnusedRects(bool sync, PlayerContext *ctx)
 {
     VERBOSE(VB_IMPORTANT, LOC + "DrawUnusedRects() -- begin");
@@ -8411,8 +8506,11 @@
     infoMap["channum"]     = browsechannum;
     infoMap["chanid"]      = browsechanid;
 
-    if (ctx->recorder)
+    ProgramInfo *program_info = NULL;
+    if (ctx->recorder && !browsealltuners)
         GetNextProgram(ctx->recorder, direction, infoMap);
+    else
+        GetNextProgramAnyTuner(direction, infoMap, program_info);
 
     browsechannum = infoMap["channum"];
     browsechanid  = infoMap["chanid"];
@@ -8423,13 +8521,20 @@
         browsestarttime = infoMap["dbstarttime"];
     }
 
-    QDateTime startts = QDateTime::fromString(browsestarttime, Qt::ISODate);
-    ProgramInfo *program_info =
-        ProgramInfo::GetProgramAtDateTime(browsechanid, startts);
+    if (!program_info)
+    {
+        QDateTime startts = QDateTime::fromString(
+            browsestarttime, Qt::ISODate);
+        program_info =
+            ProgramInfo::GetProgramAtDateTime(browsechanid, startts);
+    }
 
     if (program_info)
         program_info->ToMap(infoMap);
 
+    if (browsealltuners && !IsTunable(ctx, browsechanid.toUInt()))
+        infoMap["channum"] = "x" + infoMap["channum"];
+
     osd->ClearAllText("browse_info");
     osd->SetText("browse_info", infoMap, -1);
 
@@ -8503,8 +8608,10 @@
 
 void TV::BrowseChannel(PlayerContext *ctx, const QString &chan)
 {
-    if (!ctx->recorder || !ctx->recorder->CheckChannel(chan))
+    if (browsealltuners && !GetChanIDAnyTuner(chan))
         return;
+    else if (!ctx->recorder || !ctx->recorder->CheckChannel(chan))
+        return;
 
     browsechannum = chan;
     browsechanid = QString::null;
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 19464)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -1982,6 +1982,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");
@@ -4830,6 +4842,7 @@
     osd->addChild(OSDThemeFontSizeType());
     osd->addChild(EnableMHEG());
     osd->addChild(PersistentBrowseMode());
+    osd->addChild(BrowseAllTuners());
     addChild(osd);
 
     VerticalConfigurationGroup *udp = new VerticalConfigurationGroup(false);

