Index: libs/libmythtv/previouslist.cpp
===================================================================
--- libs/libmythtv/previouslist.cpp	(revision 10371)
+++ libs/libmythtv/previouslist.cpp	(working copy)
@@ -40,7 +40,6 @@
     hourFormat = gContext->GetSetting("TimeFormat");
     timeFormat = gContext->GetSetting("ShortDateFormat") + " " + hourFormat;
     fullDateFormat = dayFormat + " " + hourFormat;
-    channelOrdering = gContext->GetSetting("ChannelOrdering", "channum + 0");
     channelFormat = gContext->GetSetting("ChannelFormat", "<num> <sign>");
 
     allowEvents = true;
Index: libs/libmythtv/channelutil.h
===================================================================
--- libs/libmythtv/channelutil.h	(revision 10371)
+++ libs/libmythtv/channelutil.h	(working copy)
@@ -8,6 +8,33 @@
 
 class NetworkInformationTable;
 
+class DBChannel
+{
+  public:
+    DBChannel(const QString &_channum, const QString &_callsign,
+              uint _chanid, uint _major_chan, uint _minor_chan,
+              uint _favorite,
+              const QString &_name, const QString &_icon) :
+        channum(_channum), callsign(_callsign), chanid(_chanid),
+        major_chan(_major_chan), minor_chan(_minor_chan),
+        favorite(_favorite),
+        name(_name), icon(_icon) {}
+
+    bool operator == (uint _chanid) const
+        { return chanid == _chanid; }
+
+    QString channum;
+    QString callsign;
+    uint    chanid;
+    uint    major_chan;
+    uint    minor_chan;
+    uint    favorite;
+    QString name;
+    QString icon;
+};
+typedef vector<DBChannel> DBChanList;
+
+
 /** \class ChannelUtil
  *  \brief Collection of helper utilities for channel DB use
  */
@@ -97,24 +124,11 @@
     static QString GetVideoFilters(uint sourceid, const QString &channum)
         { return GetChannelValueStr("videofilters", sourceid, channum); }
 
-    static QString GetNextChannel(uint           cardid,
-                                  const QString &inputname,
-                                  const QString &channum,
-                                  int            direction,
-                                  QString       &channelorder,
-                                  uint          &chanid);
+    static DBChanList GetChannels(uint srcid, bool vis_only, QString grp="");
+    static void    SortChannels(DBChanList &list, const QString &order);
 
-    static uint    GetNextChannel(uint           cardid,
-                                  const QString &inputname,
-                                  const QString &channum,
-                                  int            direction,
-                                  QString       &channelorder)
-    {
-        uint chanid = 0;
-        GetNextChannel(cardid,    inputname,    channum,
-                       direction, channelorder, chanid);
-        return chanid;
-    }
+    static uint    GetNextChannel(const DBChanList &sorted,
+                                  uint old_chanid, int direction);
 
     static QString GetChannelValueStr(const QString &channel_field,
                                       uint           sourceid,
Index: libs/libmythtv/proglist.cpp
===================================================================
--- libs/libmythtv/proglist.cpp	(revision 10371)
+++ libs/libmythtv/proglist.cpp	(working copy)
@@ -23,6 +23,7 @@
 #include "mythcontext.h"
 #include "remoteutil.h"
 #include "mythdbcon.h"
+#include "channelutil.h"
 
 ProgLister::ProgLister(ProgListType pltype,
                        const QString &view, const QString &from,
@@ -39,7 +40,7 @@
     hourFormat = gContext->GetSetting("TimeFormat");
     timeFormat = gContext->GetSetting("ShortDateFormat") + " " + hourFormat;
     fullDateFormat = dayFormat + " " + hourFormat;
-    channelOrdering = gContext->GetSetting("ChannelOrdering", "channum + 0");
+    channelOrdering = gContext->GetSetting("ChannelOrdering", "channum");
     channelFormat = gContext->GetSetting("ChannelFormat", "<num> <sign>");
 
     switch (pltype)
@@ -977,36 +978,26 @@
     stationList.clear();
     stationList << "";
 
-    query.prepare(QString("SELECT channel.chanid, channel.channum, "
-                  "channel.callsign, channel.name FROM channel "
-                  "WHERE channel.visible = 1 "
-                  "GROUP BY callsign "
-                  "ORDER BY ") + channelOrdering + ";");
-    query.exec();
+    DBChanList channels = ChannelUtil::GetChannels(0, false, "callsign");
+    ChannelUtil::SortChannels(channels, channelOrdering);
 
-    if (query.isActive() && query.size())
+    for (uint i = 0; i < channels.size(); i++)
     {
-        while (query.next())
-        {
-            QString chanid = query.value(0).toString();
-            QString channum = query.value(1).toString();
-            QString chansign = QString::fromUtf8(query.value(2).toString());
-            QString channame = QString::fromUtf8(query.value(3).toString());
+        QString chantext = QDeepCopy<QString>(channelFormat);
+        chantext
+            .replace("<num>",  channels[i].channum)
+            .replace("<sign>", channels[i].callsign)
+            .replace("<name>", channels[i].name);
 
-            QString chantext = channelFormat;
-            chantext.replace("<num>", channum)
-                .replace("<sign>", chansign)
-                .replace("<name>", channame);
+        viewList << QString::number(channels[i].chanid);
+        viewTextList << chantext;
 
-            viewList << chanid;
-            viewTextList << chantext;
-
-            powerStation->insertItem(chantext);
-            stationList << chansign;
-            if (chansign == field[5])
-                powerStation->setCurrentItem(powerStation->count() - 1);
-        }
+        powerStation->insertItem(chantext);
+        stationList << channels[i].callsign;
+        if (channels[i].callsign == field[5])
+            powerStation->setCurrentItem(powerStation->count() - 1);
     }
+
     powerPopup->addWidget(powerStation);
 
     powerOkButton = new MythPushButton(powerPopup);
@@ -1185,33 +1176,22 @@
 
     if (type == plChannel) // list by channel
     {
-        MSqlQuery query(MSqlQuery::InitCon()); 
-        query.prepare(QString("SELECT channel.chanid, channel.channum, "
-                      "channel.callsign, channel.name FROM channel "
-                      "WHERE channel.visible = 1 "
-                      "GROUP BY channum, callsign "
-                      "ORDER BY ") + channelOrdering + ";");
-        query.exec();
+        DBChanList channels = ChannelUtil::GetChannels(0, false, "callsign");
+        ChannelUtil::SortChannels(channels, channelOrdering);
 
-        if (query.isActive() && query.size())
+        for (uint i = 0; i < channels.size(); i++)
         {
-            while (query.next())
-            {
-                QString chanid = query.value(0).toString();
-                QString channum = query.value(1).toString();
-                QString chansign = QString::fromUtf8(query.value(2).toString());
-                QString channame = QString::fromUtf8(query.value(3).toString());
+            QString chantext = QDeepCopy<QString>(channelFormat);
+            chantext
+                .replace("<num>",  channels[i].channum)
+                .replace("<sign>", channels[i].callsign)
+                .replace("<name>", channels[i].name);
 
-                QString chantext = channelFormat;
-                chantext.replace("<num>", channum)
-                    .replace("<sign>", chansign)
-                    .replace("<name>", channame);
-
-                viewList << chanid;
-                viewTextList << chantext;
-            }
+            viewList << QString::number(channels[i].chanid);
+            viewTextList << chantext;
         }
-        if (view != "")
+
+        if (!view.isEmpty())
             curView = viewList.findIndex(view);
     }
     else if (type == plCategory) // list by category
Index: libs/libmythtv/guidegrid.cpp
===================================================================
--- libs/libmythtv/guidegrid.cpp	(revision 10371)
+++ libs/libmythtv/guidegrid.cpp	(working copy)
@@ -31,6 +31,7 @@
 #include "customedit.h"
 #include "util.h"
 #include "remoteutil.h"
+#include "channelutil.h"
 
 bool RunProgramGuide(uint &chanid, QString &channum,
                      bool thread, TV *player,
@@ -179,7 +180,7 @@
             container->SetDrawFontShadow(false);
     }
 
-    channelOrdering = gContext->GetSetting("ChannelOrdering", "channum + 0");
+    channelOrdering = gContext->GetSetting("ChannelOrdering", "channum");
     dateformat = gContext->GetSetting("ShortDateFormat", "ddd d");
     unknownTitle = gContext->GetSetting("UnknownTitle", "Unknown");
     unknownCategory = gContext->GetSetting("UnknownCategory", "Unknown");
@@ -559,69 +560,34 @@
 
 void GuideGrid::fillChannelInfos(bool gotostartchannel)
 {
-    MSqlQuery query(MSqlQuery::InitCon());
-
     m_channelInfos.clear();
 
+    DBChanList channels = ChannelUtil::GetChannels(0, true, "callsign");
+    ChannelUtil::SortChannels(channels, channelOrdering);
+
     if (showFavorites)
     {
-        query.prepare(
-            "SELECT channel.channum, channel.callsign, "
-            "       channel.icon,    channel.chanid, "
-            "       favorites.favid, channel.name "
-            "FROM videosource, cardinput, favorites, channel "
-            "WHERE channel.chanid       = favorites.chanid     AND "
-            "      visible              = 1                    AND "
-            "      channel.sourceid     = videosource.sourceid AND "
-            "      videosource.sourceid = cardinput.sourceid "
-            "GROUP BY channum, callsign "
-            "ORDER BY " + channelOrdering);
-
-        if (query.exec() && query.isActive())
-            showFavorites = query.size();
-        else
-            MythContext::DBError("fillChannelInfos -- favorites", query);
-    }
-
-    if (!showFavorites)
-    {
-        query.prepare(
-            "SELECT channel.channum, channel.callsign, "
-            "       channel.icon,    channel.chanid, "
-            "       favorites.favid, channel.name "
-            "FROM videosource, cardinput, "
-            "       channel LEFT JOIN favorites "
-            "       ON favorites.chanid = channel.chanid "
-            "WHERE visible              = 1                    AND "
-            "      channel.sourceid     = videosource.sourceid AND "
-            "      videosource.sourceid = cardinput.sourceid "
-            "GROUP BY channum, callsign "
-            "ORDER BY " + channelOrdering);
-
-        if (!query.exec() || !query.isActive())
+        DBChanList tmp;
+        for (uint i = 0; i < channels.size(); i++)
         {
-            MythContext::DBError("fillChannelInfos -- all connected", query);
-            return;
+            if (channels[i].favorite)
+                tmp.push_back(channels[i]);
         }
+
+        if (!tmp.empty())
+            channels = tmp;
     }
- 
+
     bool startingset = false;
-    while (query.next())
+    for (uint i = 0; i < channels.size(); i++)
     {
         ChannelInfo val;
-
-        val.chanstr  = query.value(0).toString();
-        val.chanid   = query.value(3).toInt();
-
-        // validate the channum and chanid, skip channel if these are invalid
-        if (val.chanstr == "" || !val.chanid)
-            continue;
-
-        // fill in the rest of the data...
-        val.callsign = QString::fromUtf8(query.value(1).toString());
-        val.iconpath = query.value(2).toString();
-        val.favid    = query.value(4).toInt();
-        val.channame = QString::fromUtf8(query.value(5).toString());
+        val.chanstr  = channels[i].channum;
+        val.chanid   = channels[i].chanid;
+        val.callsign = channels[i].callsign;
+        val.favid    = channels[i].favorite;
+        val.channame = channels[i].name;
+        val.iconpath = channels[i].icon;
         val.iconload = false;
 
         // set starting channel index if it hasn't been set
@@ -633,10 +599,11 @@
             m_currentStartChannel = m_channelInfos.size();
             startingset = true;
         }
-                
+
         // add the new channel to the list
         m_channelInfos.push_back(val);
     }
+ 
     // set starting channel index to 0 if it hasn't been set
     if (gotostartchannel)
         m_currentStartChannel = (startingset) ? m_currentStartChannel : 0;
Index: libs/libmythtv/dbcheck.cpp
===================================================================
--- libs/libmythtv/dbcheck.cpp	(revision 10372)
+++ libs/libmythtv/dbcheck.cpp	(working copy)
@@ -10,7 +10,7 @@
 #include "mythdbcon.h"
 
 /// This is the DB schema version expected by the running MythTV instance.
-const QString currentDatabaseVersion = "1149";
+const QString currentDatabaseVersion = "1150";
 
 static bool UpdateDBVersionNumber(const QString &newnumber);
 static bool performActualUpdate(const QString updates[], QString version,
@@ -2365,6 +2365,17 @@
             return false;
     }
 
+    if (dbver == "1149")
+    {
+        const QString updates[] = {
+"UPDATE settings SET data='channum' WHERE value='ChannelOrdering' AND data!='callsign';",
+""
+};
+
+        if (!performActualUpdate(updates, "1150", dbver))
+            return false;
+    }
+
 //"ALTER TABLE capturecard DROP COLUMN dvb_recordts;" in 0.21
 //"ALTER TABLE capturecard DROP COLUMN dvb_hw_decoder;" in 0.21
 //"ALTER TABLE cardinput DROP COLUMN  preference;" in 0.22
Index: libs/libmythtv/channelbase.h
===================================================================
--- libs/libmythtv/channelbase.h	(revision 10371)
+++ libs/libmythtv/channelbase.h	(working copy)
@@ -10,7 +10,7 @@
 #include <qsqldatabase.h>
 
 // MythTV headers
-
+#include "channelutil.h"
 #include "frequencies.h"
 #include "tv.h"
 
@@ -31,10 +31,12 @@
 
     InputBase(QString _name,            QString _startChanNum,
               QString _tuneToChannel,   QString _externalChanger,
-              uint    _sourceid,        uint    _cardid) :
+              uint    _sourceid,        uint    _cardid,
+              const DBChanList &_channels) :
         name(_name),                    startChanNum(_startChanNum),
         tuneToChannel(_tuneToChannel),  externalChanger(_externalChanger),
         sourceid(_sourceid),            cardid(_cardid),
+        channels(_channels),
         inputNumV4L(-1),
         videoModeV4L1(0),               videoModeV4L2(0) {}
 
@@ -47,6 +49,7 @@
     QString externalChanger; // for using a cable box...
     uint    sourceid;        // associated channel listings source
     uint    cardid;          // input card id
+    DBChanList channels;
     int     inputNumV4L;
     int     videoModeV4L1;
     int     videoModeV4L2;
@@ -83,6 +86,8 @@
     virtual int GetFd(void) const { return -1; };
 
     // Gets
+    virtual uint GetNextChannel(uint chanid, int direction) const;
+    virtual uint GetNextChannel(const QString &channum, int direction) const;
     virtual int GetInputByName(const QString &input) const;
     virtual QString GetInputByNum(int capchannel) const;
     virtual QString GetCurrentName(void) const
@@ -101,8 +106,6 @@
         { return inputs[GetCurrentInputNum()]->sourceid; }
     virtual uint GetInputCardID(int inputNum) const;
     virtual QStringList GetConnectedInputs(void) const;
-    virtual QString GetOrdering(void) const
-        { return channelorder; }
     /// \brief Returns true iff commercial detection is not required
     //         on current channel, for BBC, CBC, etc.
     bool IsCommercialFree(void) const { return commfree; }
@@ -110,8 +113,6 @@
     virtual QString GetDevice(void) const { return ""; }
 
     // Sets
-    virtual void SetChannelOrdering(const QString &chanorder)
-        { channelorder = chanorder; }
     virtual void Renumber(uint srcid, const QString &oldChanNum,
                           const QString &newChanNum);
 
@@ -177,7 +178,6 @@
     static void StoreInputChannels(const InputMap&);
 
     TVRec   *pParent;
-    QString  channelorder;
     QString  curchannelname;
     int      currentInputID;
     bool     commfree;
Index: libs/libmythtv/previouslist.h
===================================================================
--- libs/libmythtv/previouslist.h	(revision 10371)
+++ libs/libmythtv/previouslist.h	(working copy)
@@ -48,7 +48,6 @@
     QString hourFormat;
     QString timeFormat;
     QString fullDateFormat;
-    QString channelOrdering;
     QString channelFormat;
 
     RecSearchType searchtype;
Index: libs/libmythtv/channelbase.cpp
===================================================================
--- libs/libmythtv/channelbase.cpp	(revision 10371)
+++ libs/libmythtv/channelbase.cpp	(working copy)
@@ -32,7 +32,7 @@
 
 ChannelBase::ChannelBase(TVRec *parent)
     : 
-    pParent(parent), channelorder("channum + 0"), curchannelname(""),
+    pParent(parent), curchannelname(""),
     currentInputID(-1), commfree(false), cardid(0),
     currentATSCMajorChannel(-1), currentATSCMinorChannel(-1),
     currentProgramNum(-1), currentOriginalNetworkID(-1), 
@@ -46,28 +46,39 @@
 
 bool ChannelBase::SetChannelByDirection(ChannelChangeDirection dir)
 {
-    bool fTune = false;
-    uint chanid;
-    QString start, nextchan;
-    start = nextchan = ChannelUtil::GetNextChannel(
-        GetCardID(), GetCurrentInput(), GetCurrentName(),
-        dir,         channelorder,      chanid);
+    uint startchanid = GetNextChannel(GetCurrentName(), dir);
+    uint nextchanid  = startchanid;
 
+    bool ok = false;
     do
     {
-       fTune = SetChannelByString(nextchan);
-       if (!fTune)
-       {
-           nextchan = ChannelUtil::GetNextChannel(
-               GetCardID(), GetCurrentInput(), GetCurrentName(),
-               dir,         channelorder,      chanid);
-       }
+        if (!(ok = SetChannelByString(ChannelUtil::GetChanNum(nextchanid))))
+            nextchanid = GetNextChannel(nextchanid, dir);
     }
-    while (!fTune && nextchan != start);
+    while (!ok && (nextchanid != startchanid));
 
-    return fTune;
+    return ok;
 }
 
+uint ChannelBase::GetNextChannel(uint chanid, int direction) const
+{
+    InputMap::const_iterator it = inputs.find(currentInputID);
+    if (it == inputs.end())
+        return 0;
+
+    return ChannelUtil::GetNextChannel((*it)->channels, chanid, direction);
+}
+
+uint ChannelBase::GetNextChannel(const QString &channum, int direction) const
+{
+    InputMap::const_iterator it = inputs.find(currentInputID);
+    if (it == inputs.end())
+        return 0;
+
+    uint chanid = ChannelUtil::GetChanID((*it)->sourceid, channum);
+    return GetNextChannel(chanid, direction);
+}
+
 int ChannelBase::GetNextInputNum(void) const
 {
     // Exit early if inputs don't exist..
@@ -486,10 +497,16 @@
         uint inputcardid = query.value(6).toUInt();
         inputcardid = (inputcardid) ? inputcardid : cardid;
 
+        uint sourceid = query.value(5).toUInt();
+        DBChanList channels = ChannelUtil::GetChannels(sourceid, false);
+
+        QString order = gContext->GetSetting("ChannelOrdering", "channum");
+        ChannelUtil::SortChannels(channels, order);
+
         inputs[query.value(0).toUInt()] = new InputBase(
             query.value(1).toString(), query.value(2).toString(),
             query.value(3).toString(), query.value(4).toString(),
-            query.value(5).toUInt(),   inputcardid);
+            sourceid, inputcardid, channels);
     }
 
     // Set initial input to first connected input
Index: libs/libmythtv/channelutil.cpp
===================================================================
--- libs/libmythtv/channelutil.cpp	(revision 10371)
+++ libs/libmythtv/channelutil.cpp	(working copy)
@@ -796,192 +796,6 @@
     return query.exec();
 }
 
-QString ChannelUtil::GetNextChannel(
-    uint           cardid,       const QString &inputname,
-    const QString &channum,      int            direction,
-    QString       &channelorder, uint          &chanid)
-{
-    chanid = 0;
-    bool isNum = true;
-    channum.toULong(&isNum);
-
-    if (!isNum && channelorder == "channum + 0")
-    {
-        bool has_atsc = GetChannelValueInt("atscsrcid", cardid,
-                                           inputname, channum);
-        channelorder = (has_atsc) ? "atscsrcid" : "channum";
-        if (!has_atsc)
-        {
-            QString msg = QString(
-                "Your channel ordering method \"channel number (numeric)\"\n"
-                "\t\t\twill not work with channels like: '%1' \n"
-                "\t\t\tConsider switching to order by \"database order\"  \n"
-                "\t\t\tor \"channel number (alpha)\" in the general       \n"
-                "\t\t\tsettings section of the frontend setup             \n"
-                "\t\t\tSwitched to '%2' order.")
-                .arg(channum).arg(channelorder);
-            VERBOSE(VB_IMPORTANT, LOC + msg);
-        }
-    }
-
-    MSqlQuery query(MSqlQuery::InitCon());
-
-    QString querystr = QString(
-        "SELECT %1 "
-        "FROM channel,capturecard,cardinput "
-        "WHERE channel.channum      = :CHANNUM           AND "
-        "      channel.sourceid     = cardinput.sourceid AND "
-        "      cardinput.cardid     = capturecard.cardid AND "
-        "      capturecard.cardid   = :CARDID            AND "
-        "      capturecard.hostname = :HOSTNAME").arg(channelorder);
-    query.prepare(querystr);
-    query.bindValue(":CHANNUM",  channum);
-    query.bindValue(":CARDID",   cardid);
-    query.bindValue(":HOSTNAME", gContext->GetHostName());
-
-    QString id = QString::null;
-
-    if (!query.exec() || !query.isActive())
-        MythContext::DBError("getnextchannel 1", query);
-    else if (query.next())
-        id = query.value(0).toString();
-
-    if (id.isEmpty())
-    {
-        QString msg = QString(
-            "Channel: '%1' was not found in the database.\n"
-            "\t\t\tMost likely, the default channel set for this input\n"
-            "\t\t\tcardid %2, input '%3'\n"
-            "\t\t\tin setup is wrong\n")
-            .arg(channum).arg(cardid).arg(inputname);
-        VERBOSE(VB_IMPORTANT, LOC + msg);
-
-        querystr = QString(
-            "SELECT %1 "
-            "FROM channel, capturecard, cardinput "
-            "WHERE channel.sourceid     = cardinput.sourceid AND "
-            "      cardinput.cardid     = capturecard.cardid AND "
-            "      capturecard.cardid   = :CARDID            AND "
-            "      capturecard.hostname = :HOSTNAME "
-            "ORDER BY %2 "
-            "LIMIT 1").arg(channelorder).arg(channelorder);
-        query.prepare(querystr);
-        query.bindValue(":CARDID",   cardid);
-        query.bindValue(":HOSTNAME", gContext->GetHostName());
-
-        if (!query.exec() || !query.isActive())
-            MythContext::DBError("getnextchannel 2", query);
-        else if (query.next())
-            id = query.value(0).toString();
-    }
-
-    if (id.isEmpty())
-    {
-        VERBOSE(VB_IMPORTANT, LOC_ERR +
-                "Couldn't find any channels in the database,\n"
-                "\t\t\tplease make sure your inputs are associated\n"
-                "\t\t\tproperly with your cards.");
-        return "";
-    }
-
-    // Now let's try finding the next channel in the desired direction
-    QString comp = ">";
-    QString ordering = "";
-    QString fromfavorites = "";
-    QString wherefavorites = "";
-
-    if (direction == CHANNEL_DIRECTION_DOWN)
-    {
-        comp = "<";
-        ordering = " DESC ";
-    }
-    else if (direction == CHANNEL_DIRECTION_FAVORITE)
-    {
-        fromfavorites = ",favorites";
-        wherefavorites = "AND favorites.chanid = channel.chanid";
-    }
-    else if (direction == CHANNEL_DIRECTION_SAME)
-    {
-        comp = "=";
-    }
-
-    QString wherepart = QString(
-        "cardinput.cardid     = capturecard.cardid AND "
-        "capturecard.cardid   = :CARDID            AND "
-        "capturecard.hostname = :HOSTNAME          AND "
-        "channel.visible      = 1                  AND "
-        "cardinput.sourceid = channel.sourceid ");
-
-    querystr = QString(
-        "SELECT channel.channum, channel.chanid "
-        "FROM channel, capturecard, cardinput%1 "
-        "WHERE channel.%2 %3 :ID %4 AND "
-        "      %5 "
-        "ORDER BY channel.%6 %7 "
-        "LIMIT 1")
-        .arg(fromfavorites).arg(channelorder)
-        .arg(comp).arg(wherefavorites)
-        .arg(wherepart).arg(channelorder).arg(ordering);
-
-    query.prepare(querystr);
-    query.bindValue(":CARDID",   cardid);
-    query.bindValue(":HOSTNAME", gContext->GetHostName());
-    query.bindValue(":ID",       id);
-
-    if (!query.exec() || !query.isActive())
-    {
-        MythContext::DBError("getnextchannel 3", query);
-    }
-    else if (query.next())
-    {
-        chanid = query.value(1).toUInt();
-        return query.value(0).toString();
-    }
-    else
-    {
-        // Couldn't find the channel going in the desired direction, 
-        // so loop around and find it on the flip side...
-        comp = "<";
-        if (direction == CHANNEL_DIRECTION_DOWN) 
-            comp = ">";
-
-        // again, %9 is the limit for this
-        querystr = QString(
-            "SELECT channel.channum, channel.chanid "
-            "FROM channel, capturecard, cardinput%1 "
-            "WHERE channel.%2 %3 :ID %4 AND "
-            "      %5 "
-            "ORDER BY channel.%6 %7 "
-            "LIMIT 1")
-            .arg(fromfavorites).arg(channelorder)
-            .arg(comp).arg(wherefavorites)
-            .arg(wherepart).arg(channelorder).arg(ordering);
-
-        query.prepare(querystr);
-        query.bindValue(":CARDID",   cardid);
-        query.bindValue(":HOSTNAME", gContext->GetHostName());
-        query.bindValue(":ID",       id); 
-
-        if (!query.exec() || !query.isActive())
-        {
-            MythContext::DBError("getnextchannel", query);
-        }
-        else if (query.next())
-        {
-            chanid = query.value(1).toUInt();
-            return query.value(0).toString();
-        }
-        else
-        {
-            VERBOSE(VB_IMPORTANT, "getnextchannel, query failed: "<<querystr);
-        }
-    }
-
-    // just stay on same channel
-    chanid = max(GetChannelValueInt("chanid", cardid, inputname, channum), 0);
-    return channum;
-}
-
 int ChannelUtil::GetChanID(int mplexid,       int service_transport_id,
                            int major_channel, int minor_channel,
                            int program_number)
@@ -1244,7 +1058,7 @@
         query.bindValue(":CHANNUM",   chan_num);
     if (freqid > 0)
         query.bindValue(":FREQID",    freqid);
-    if (atsc_major_channel > 0)
+    if (atsc_minor_channel > 0)
         query.bindValue(":TVFORMAT",  "ATSC");
 
     if (!query.exec() || !query.isActive())
@@ -1321,3 +1135,155 @@
 
     return query.value(0).toString();
 }
+
+DBChanList ChannelUtil::GetChannels(uint sourceid, bool vis_only, QString grp)
+{
+    DBChanList list;
+    QMap<uint,uint> favorites;
+    MSqlQuery query(MSqlQuery::InitCon());
+    query.prepare(
+        "SELECT chanid, favid "
+        "FROM favorites");
+    if (!query.exec() || !query.isActive())
+        MythContext::DBError("get channels -- favorites", query);
+    else
+    {
+        while (query.next())
+            favorites[query.value(0).toUInt()] = query.value(1).toUInt();
+    }
+
+    QString qstr =
+        "SELECT channum, callsign, chanid, "
+        "       atscsrcid/256, atscsrcid%255, "
+        "       name, icon "
+        "FROM channel ";
+
+    if (sourceid)
+        qstr += QString("WHERE sourceid='%1' ").arg(sourceid);
+    else
+        qstr += ",cardinput,capturecard "
+            "WHERE cardinput.sourceid = channel.sourceid   AND "
+            "      cardinput.cardid   = capturecard.cardid     ";
+
+    if (vis_only)
+        qstr += "AND visible=1 ";
+
+    if (!grp.isEmpty())
+        qstr += QString("GROUP BY %1 ").arg(grp);
+
+    query.prepare(qstr);
+    if (!query.exec() || !query.isActive())
+    {
+        MythContext::DBError("get channels -- sourceid", query);
+        return list;
+    }
+
+    while (query.next())
+    {
+        if (query.value(0).toString().isEmpty() || !query.value(2).toUInt())
+            continue; // skip if channum blank, or chanid empty
+
+        DBChannel chan(
+            query.value(0).toString(),                    /* channum    */
+            QString::fromUtf8(query.value(1).toString()), /* callsign   */
+            query.value(2).toUInt(),                      /* chanid     */
+            query.value(3).toUInt(),                      /* ATSC major */
+            query.value(4).toUInt(),                      /* ATSC minor */
+            favorites[query.value(2).toUInt()],           /* favid      */
+            QString::fromUtf8(query.value(5).toString()), /* name       */
+            query.value(6).toString());                   /* icon       */
+
+        list.push_back(chan);
+    }
+
+    return list;
+}
+
+inline bool lt_callsign(const DBChannel &a, const DBChannel &b)
+{
+    return QString::localeAwareCompare(a.callsign, b.callsign) < 0;
+}
+
+inline bool lt_smart(const DBChannel &a, const DBChannel &b)
+{
+    int cmp = 0;
+    if (a.major_chan && b.major_chan)
+    {
+        if ((cmp = a.major_chan - b.major_chan))
+            return cmp < 0;
+
+        if ((cmp = a.minor_chan - b.minor_chan))
+            return cmp < 0;
+    }
+
+    bool isIntA, isIntB;
+    int a_int = a.channum.toUInt(&isIntA);
+    int b_int = a.channum.toUInt(&isIntB);
+    if (isIntA && isIntB)
+    {
+        cmp = a_int - b_int;
+        if (cmp)
+            return cmp < 0;
+    }
+    else
+    {
+        return QString::localeAwareCompare(a.channum, b.channum) < 0;
+    }
+
+    return lt_callsign(a,b);
+}
+
+void ChannelUtil::SortChannels(DBChanList &list, const QString &order)
+{
+    if (order.lower() == "callsign")
+        sort(list.begin(), list.end(), lt_callsign);
+    else /* if (sortorder == "channum") */
+        sort(list.begin(), list.end(), lt_smart);
+}
+
+uint ChannelUtil::GetNextChannel(const DBChanList &sorted,
+                                 uint old_chanid, int direction)
+{
+    DBChanList::const_iterator it =
+        find(sorted.begin(), sorted.end(), old_chanid);
+
+    if (it == sorted.end())
+        it = sorted.begin(); // not in list, pretend we are on first channel
+
+    if (it == sorted.end())
+        return 0; // no channels..
+
+    if (CHANNEL_DIRECTION_DOWN == direction)
+    {
+        if (it == sorted.begin())
+            return sorted.rbegin()->chanid;
+        it--;
+    }
+    else if (CHANNEL_DIRECTION_UP == direction)
+    {
+        it++;
+        if (it == sorted.end())
+            it = sorted.begin();
+    }
+    else if (CHANNEL_DIRECTION_FAVORITE == direction)
+    {
+        DBChanList::const_iterator it_orig = it;
+        for (;;++it)
+        {
+            if (it == sorted.end())
+                it = sorted.begin();
+
+            if (it == it_orig)
+            {
+                if (!it->favorite)
+                    ++it;
+                break; // no (other?) favorites
+            }
+
+            if (it->favorite)
+                break; // found next favorite
+        }
+    }
+
+    return it->chanid;
+}
Index: libs/libmythtv/videosource.cpp
===================================================================
--- libs/libmythtv/videosource.cpp	(revision 10371)
+++ libs/libmythtv/videosource.cpp	(working copy)
@@ -29,6 +29,7 @@
 #include "scanwizard.h"
 #include "cardutil.h"
 #include "sourceutil.h"
+#include "channelutil.h"
 #include "frequencies.h"
 
 #ifdef USING_DVB
@@ -1614,34 +1615,24 @@
     else if (query.next())
         startChan = query.value(0).toString();
 
-    // Get the existing channels on the connected source
-    query.prepare(
-        "SELECT channum "
-        "FROM channel "
-        "WHERE sourceid = :SOURCEID "
-        "ORDER BY atscsrcid, channum");
-    query.bindValue(":SOURCEID", sourceid.toUInt());
+    DBChanList channels = ChannelUtil::GetChannels(sourceid.toUInt(), false);
 
-    QString nnsc = startChan.isEmpty() ? "" : startChan;
-    if (!query.exec() || !query.isActive())
+    if (channels.empty())
     {
-        addSelection(tr("DB Error, see console"), nnsc);
-        MythContext::DBError("SetSourceID -- get channels", query);
+        addSelection(tr("Please add channels to this source"),
+                     startChan.isEmpty() ? "" : startChan);
+        return;
     }
-    else if (query.size() > 0)
+
+    // If there are channels sort them, then add them 
+    // (selecting the old start channel if it is there).
+    QString order = gContext->GetSetting("ChannelOrdering", "channum");
+    ChannelUtil::SortChannels(channels, order);
+    for (uint i = 0; i < channels.size(); i++)
     {
-        // If there are channels add them, and
-        // highlight the old start channel
-        while (query.next())
-        {
-            const QString channum = query.value(0).toString();
-            addSelection(channum, channum, channum == startChan);
-        }
+        const QString channum = channels[i].channum;
+        addSelection(channum, channum, channum == startChan);
     }
-    else
-    {
-        addSelection(tr("Please add channels to this source"), nnsc);
-    }
 }
 
 class InputPriority: public SpinBoxSetting, public CISetting {
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 10371)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -1069,12 +1069,6 @@
         channel->SetChannelByString(startchannel);
     else
         channel->SwitchToInput(inputname, startchannel);
-
-    // Set channel ordering, and check validity...
-    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum + 0");
-    ChannelUtil::GetNextChannel(cardid, inputname, startchannel,
-                                BROWSE_SAME, chanorder);
-    channel->SetChannelOrdering(chanorder);
 }
 
 void TVRec::CloseChannel(void)
@@ -2815,32 +2809,24 @@
 {
     QString compare     = "<=";
     QString sortorder   = "desc";
-    QString input       = channel->GetCurrentInput();
-    QString order       = channel->GetOrdering();
-    int     chanid      = -1;
+    uint     chanid     = 0;
 
     if (BROWSE_SAME == direction)
-        chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_SAME, order);
+        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
     else if (BROWSE_UP == direction)
-        chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_UP, order);
+        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_UP);
     else if (BROWSE_DOWN == direction)
-        chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_DOWN, order);
+        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_DOWN);
     else if (BROWSE_FAVORITE == direction)
-        chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_FAVORITE, order);
+        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_FAVORITE);
     else if (BROWSE_LEFT == direction)
     {
-        chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_SAME, order);
+        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
         compare = "<";
     }
     else if (BROWSE_RIGHT == direction)
     {
-	chanid = ChannelUtil::GetNextChannel(
-            cardid, input, channum, CHANNEL_DIRECTION_SAME, order);
+	chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
         compare = ">";
         sortorder = "asc";
     }
@@ -3047,13 +3033,9 @@
 
     if (channel && !channum.isEmpty() && (channum.find("NextChannel") >= 0))
     {
-        int dir = channum.right(channum.length() - 12).toInt();
-        uint chanid;
-        QString channelordering = channel->GetOrdering();
-        channum = ChannelUtil::GetNextChannel(
-            cardid,                    channel->GetCurrentInput(),
-            channel->GetCurrentName(), dir,
-            channelordering,           chanid);
+        int dir     = channum.right(channum.length() - 12).toInt();
+        uint chanid = channel->GetNextChannel(0, dir);
+        channum     = ChannelUtil::GetChanNum(chanid);
     }
 
     return channum;
Index: libs/libmythtv/programinfo.cpp
===================================================================
--- libs/libmythtv/programinfo.cpp	(revision 10371)
+++ libs/libmythtv/programinfo.cpp	(working copy)
@@ -4002,8 +4002,7 @@
         querystr += " GROUP BY program.starttime, channel.channum, "
             "  channel.callsign, program.title ";
     if (!sql.contains(" ORDER BY "))
-        querystr += QString(" ORDER BY program.starttime, ") + 
-                    gContext->GetSetting("ChannelOrdering", "channum+0") + " ";
+        querystr += " ORDER BY program.starttime, program.chanid ";
     if (!sql.contains(" LIMIT "))
         querystr += " LIMIT 1000 ";
 
@@ -4096,7 +4095,6 @@
 
     QString ip        = gContext->GetSetting("BackendServerIP");
     QString port      = gContext->GetSetting("BackendServerPort");
-    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum + 0");
 
     // ----------------------------------------------------------------------
 
@@ -4134,38 +4132,49 @@
 
     // ----------------------------------------------------------------------
 
-    QString thequery = "SELECT recorded.chanid,recorded.starttime,recorded.endtime,"
-                       "recorded.title,recorded.subtitle,recorded.description,"
-                       "recorded.hostname,channum,name,callsign,commflagged,cutlist,"
-                       "recorded.autoexpire,editing,bookmark,recorded.category,"
-                       "recorded.recgroup,record.dupin,record.dupmethod,"
-                       "record.recordid,outputfilters,"
-                       "recorded.seriesid,recorded.programid,recorded.filesize, "
-                       "recorded.lastmodified, recorded.findid, "
-                       "recorded.originalairdate, recorded.playgroup, "
-                       "recorded.basename, recorded.progstart, "
-                       "recorded.progend, recorded.stars, "
-                       "recordedprogram.stereo, recordedprogram.hdtv, "
-                       "recordedprogram.closecaptioned "
-                       "FROM recorded "
-                       "LEFT JOIN record ON recorded.recordid = record.recordid "
-                       "LEFT JOIN channel ON recorded.chanid = channel.chanid "
-                       "LEFT JOIN recordedprogram ON (recorded.chanid = recordedprogram.chanid "
-                              "AND recorded.starttime = recordedprogram.starttime) "
-                       "WHERE (recorded.deletepending = 0 OR "
-                              "DATE_ADD(recorded.lastmodified, "
-                                       "INTERVAL 5 MINUTE) <= NOW()) "
-                       "ORDER BY recorded.starttime";
+    QString thequery =
+        "SELECT recorded.chanid,recorded.starttime,recorded.endtime,"
+        "recorded.title,recorded.subtitle,recorded.description,"
+        "recorded.hostname,channum,name,callsign,commflagged,cutlist,"
+        "recorded.autoexpire,editing,bookmark,recorded.category,"
+        "recorded.recgroup,record.dupin,record.dupmethod,"
+        "record.recordid,outputfilters,"
+        "recorded.seriesid,recorded.programid,recorded.filesize, "
+        "recorded.lastmodified, recorded.findid, "
+        "recorded.originalairdate, recorded.playgroup, "
+        "recorded.basename, recorded.progstart, "
+        "recorded.progend, recorded.stars, "
+        "recordedprogram.stereo, recordedprogram.hdtv, "
+        "recordedprogram.closecaptioned "
+        "FROM recorded "
+        "LEFT JOIN record ON recorded.recordid = record.recordid "
+        "LEFT JOIN channel ON recorded.chanid = channel.chanid "
+        "LEFT JOIN recordedprogram ON "
+        " ( recorded.chanid    = recordedprogram.chanid AND "
+        "   recorded.starttime = recordedprogram.starttime ) "
+        "WHERE ( recorded.deletepending = 0 OR "
+        "        DATE_ADD(recorded.lastmodified,  INTERVAL 5 MINUTE) <= NOW() "
+        "      ) "
+        "ORDER BY recorded.starttime";
 
     if ( bDescending )
         thequery += " DESC";
 
-    thequery += ", " + chanorder + " DESC;";
+    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum");
+    if (chanorder != "channum")
+        thequery += ", " + chanorder + " DESC;";
+    else // approximation which the DB can handle
+        thequery += ",atscsrcid/256,atscsrcid%255,channum,callsign DESC;";
 
     query.prepare(thequery);
 
-    if (query.exec() && query.isActive() && query.size() > 0)
+    if (!query.exec() || !query.isActive())
     {
+        MythContext::DBError("ProgramList::FromRecorded", query);
+        return true;
+    }
+    else
+    {
         while (query.next())
         {
             ProgramInfo *proginfo = new ProgramInfo;
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
--- programs/mythfrontend/globalsettings.cpp	(revision 10371)
+++ programs/mythfrontend/globalsettings.cpp	(working copy)
@@ -983,11 +983,8 @@
 {
     HostComboBox *gc = new HostComboBox("ChannelOrdering");
     gc->setLabel(QObject::tr("Channel ordering"));
-    gc->addSelection(QObject::tr("channel number (numeric)"), "channum + 0");
-    gc->addSelection(QObject::tr("channel number (alpha)"), "channum");
-    gc->addSelection(QObject::tr("database order"), "chanid");
-    gc->addSelection(QObject::tr("channel name"), "callsign");
-    gc->addSelection(QObject::tr("ATSC channel"), "atscsrcid");
+    gc->addSelection(QObject::tr("channel number"), "channum");
+    gc->addSelection(QObject::tr("channel name"),   "callsign");
     return gc;
 }
 
Index: programs/mythfrontend/manualschedule.cpp
===================================================================
--- programs/mythfrontend/manualschedule.cpp	(revision 10371)
+++ programs/mythfrontend/manualschedule.cpp	(working copy)
@@ -34,6 +34,7 @@
 #include "libmythtv/scheduledrecording.h"
 #include "libmythtv/recordingtypes.h"
 #include "libmythtv/remoteutil.h"
+#include "libmythtv/channelutil.h"
 
 ManualSchedule::ManualSchedule(MythMainWindow *parent, const char *name)
               : MythDialog(parent, name)
@@ -72,26 +73,22 @@
     m_channel->setBackgroundOrigin(WindowOrigin);
 
 
-    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum + 0");
+    QString longChannelFormat = gContext->GetSetting("LongChannelFormat",
+                                                     "<num> <name>");
+    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum");
+    DBChanList channels = ChannelUtil::GetChannels(0, false, "callsign");
+    ChannelUtil::SortChannels(channels, chanorder);
 
-    MSqlQuery query(MSqlQuery::InitCon());
-    query.prepare(QString("SELECT chanid, channum, callsign, name "
-                          "FROM channel GROUP BY channum, callsign "
-                          "ORDER BY %1;").arg(chanorder));
+    for (uint i = 0; i < channels.size(); i++)
+    {
+        QString chantext = QDeepCopy<QString>(longChannelFormat);
+        chantext
+            .replace("<num>",  channels[i].channum)
+            .replace("<sign>", channels[i].callsign)
+            .replace("<name>", channels[i].name);
 
-    QString longChannelFormat = 
-        gContext->GetSetting("LongChannelFormat", "<num> <name>");
-
-    if (query.exec() && query.isActive() && query.size()) {
-      while(query.next()) {
-          QString channel = longChannelFormat;
-          channel.replace("<num>", query.value(1).toString())
-              .replace("<sign>", QString::fromUtf8(query.value(2).toString()))
-              .replace("<name>", QString::fromUtf8(query.value(3).toString()));
-          m_channel->insertItem(channel);
-          m_chanids << query.value(0).toString();
-      }
-      
+        m_channel->insertItem(chantext);
+        m_chanids << QString::number(channels[i].chanid);
     }
 
     hbox->addWidget(m_channel);
Index: programs/mythbackend/mainserver.cpp
===================================================================
--- programs/mythbackend/mainserver.cpp	(revision 10371)
+++ programs/mythbackend/mainserver.cpp	(working copy)
@@ -987,7 +987,6 @@
 
     QString ip = gContext->GetSetting("BackendServerIP");
     QString port = gContext->GetSetting("BackendServerPort");
-    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum + 0");
 
     QMap<QString, int> inUseMap;
     QString inUseKey;
@@ -1019,34 +1018,40 @@
         }
 
 
-    QString thequery = "SELECT recorded.chanid,recorded.starttime,recorded.endtime,"
-                       "recorded.title,recorded.subtitle,recorded.description,"
-                       "recorded.hostname,channum,name,callsign,commflagged,cutlist,"
-                       "recorded.autoexpire,editing,bookmark,recorded.category,"
-                       "recorded.recgroup,record.dupin,record.dupmethod,"
-                       "record.recordid,outputfilters,"
-                       "recorded.seriesid,recorded.programid,recorded.filesize, "
-                       "recorded.lastmodified, recorded.findid, "
-                       "recorded.originalairdate, recorded.playgroup, "
-                       "recorded.basename, recorded.progstart, "
-                       "recorded.progend, recorded.stars, "
-                       "recordedprogram.stereo, recordedprogram.hdtv, "
-                       "recordedprogram.closecaptioned, transcoded, "
-                       "recorded.recpriority "
-                       "FROM recorded "
-                       "LEFT JOIN record ON recorded.recordid = record.recordid "
-                       "LEFT JOIN channel ON recorded.chanid = channel.chanid "
-                       "LEFT JOIN recordedprogram ON (recorded.chanid = recordedprogram.chanid "
-                              "AND recorded.starttime = recordedprogram.starttime) "
-                       "WHERE (recorded.deletepending = 0 OR "
-                              "DATE_ADD(recorded.lastmodified, "
-                                       "INTERVAL 5 MINUTE) <= NOW()) "
-                       "ORDER BY recorded.starttime";
+    QString thequery =
+        "SELECT recorded.chanid,recorded.starttime,recorded.endtime,"
+        "recorded.title,recorded.subtitle,recorded.description,"
+        "recorded.hostname,channum,name,callsign,commflagged,cutlist,"
+        "recorded.autoexpire,editing,bookmark,recorded.category,"
+        "recorded.recgroup,record.dupin,record.dupmethod,"
+        "record.recordid,outputfilters,"
+        "recorded.seriesid,recorded.programid,recorded.filesize, "
+        "recorded.lastmodified, recorded.findid, "
+        "recorded.originalairdate, recorded.playgroup, "
+        "recorded.basename, recorded.progstart, "
+        "recorded.progend, recorded.stars, "
+        "recordedprogram.stereo, recordedprogram.hdtv, "
+        "recordedprogram.closecaptioned, transcoded, "
+        "recorded.recpriority "
+        "FROM recorded "
+        "LEFT JOIN record ON recorded.recordid = record.recordid "
+        "LEFT JOIN channel ON recorded.chanid = channel.chanid "
+        "LEFT JOIN recordedprogram ON "
+        " ( recorded.chanid = recordedprogram.chanid AND "
+        "  recorded.starttime = recordedprogram.starttime ) "
+        "WHERE ( recorded.deletepending = 0 OR "
+        "        DATE_ADD(recorded.lastmodified, INTERVAL 5 MINUTE) <= NOW() "
+        "      ) "
+        "ORDER BY recorded.starttime";
 
     if (type == "Delete")
         thequery += " DESC";
 
-    thequery += ", " + chanorder + " DESC;";
+    QString chanorder = gContext->GetSetting("ChannelOrdering", "channum");
+    if (chanorder != "channum")
+        thequery += ", " + chanorder + " DESC;";
+    else // approximation which the DB can handle
+        thequery += ",atscsrcid/256,atscsrcid%255,channum,callsign DESC;";
 
     QStringList outputlist;
     QString fileprefix = gContext->GetFilePrefix();
@@ -1055,8 +1060,13 @@
 
     query.prepare(thequery);
 
-    if (query.exec() && query.isActive() && query.size() > 0)
+    if (!query.exec() || !query.isActive())
     {
+        MythContext::DBError("ProgramList::FromRecorded", query);
+        outputlist << "0";
+    }
+    else
+    {
         outputlist << QString::number(query.size());
 
         while (query.next())
@@ -1248,8 +1258,6 @@
             delete proginfo;
         }
     }
-    else
-        outputlist << "0";
 
     for (ri = schedList.begin(); ri != schedList.end(); ri++)
         delete (*ri);
