Index: libs/libmythtv/channelbase.h
===================================================================
--- libs/libmythtv/channelbase.h	(revision 15101)
+++ libs/libmythtv/channelbase.h	(working copy)
@@ -144,7 +144,10 @@
     virtual bool SwitchToInput(int newcapchannel, bool setstarting) = 0;
 
     virtual int GetCardID(void) const;
-    virtual bool ChangeExternalChannel(const QString &newchan);
+    virtual bool ChangeExternalChannel(const QString &channum);
+    virtual bool RotateAntenna(const QString &channum,
+                               const QString &channum,
+                               const QString &callsign);
     static void StoreInputChannels(const InputMap&);
     static void StoreDefaultInput(uint cardid, const QString &input);
 
Index: libs/libmythtv/hdhrchannel.cpp
===================================================================
--- libs/libmythtv/hdhrchannel.cpp	(revision 15101)
+++ libs/libmythtv/hdhrchannel.cpp	(working copy)
@@ -309,23 +309,27 @@
     bool isFrequency = ok && (frequency > 10000000);
 
     // Tune to proper frequency
-    if ((*it)->externalChanger.isEmpty())
+    if (isFrequency)
     {
-        if (isFrequency)
+        // Allow an antenna rotor to spin around
+        if (!(*it)->externalChanger.isEmpty())
         {
-            if (!Tune(frequency, inputName, modulation, si_std))
+            int chanid = ChannelUtil::GetChanID((*it)->sourceid, channum);
+            QString callsign = ChannelUtil::GetCallsign(chanid);
+            if (!RotateAntenna(freqid, channum, callsign))
                 return false;
         }
-        else
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    "dtv_multiplex data is required for tuning");
 
+        if (!Tune(frequency, inputName, modulation, si_std))
             return false;
-        }
     }
-    else if (!ChangeExternalChannel(freqid))
+    else
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR +
+                "dtv_multiplex data is required for tuning");
+
         return false;
+    }
 
     // Set the current channum to the new channel's channum
     curchannelname = QDeepCopy<QString>(channum);
Index: libs/libmythtv/channelbase.cpp
===================================================================
--- libs/libmythtv/channelbase.cpp	(revision 15101)
+++ libs/libmythtv/channelbase.cpp	(working copy)
@@ -223,15 +223,23 @@
     return GetChannels(inputid);
 }
 
-bool ChannelBase::ChangeExternalChannel(const QString &channum)
+bool ChannelBase::ChangeExternalChannel(const QString &freqId)
 {
+    QString empty;
+    RotateAntenna(freqId, empty, empty);
+}
+
+bool ChannelBase::RotateAntenna(const QString &freqId,
+                                const QString &channum,
+                                const QString &callsign)
+{
     InputMap::const_iterator it = inputs.find(currentInputID);
     QString changer = (*it)->externalChanger;
 
     if (changer.isEmpty())
         return false;
 
-    QString command = QString("%1 %2").arg(changer).arg(channum);
+    QString command = QString("%1 %2 %3 %4").arg(changer).arg(freqId).arg(channum).arg(callsign);
 
     VERBOSE(VB_CHANNEL, QString("External channel change: %1").arg(command));
     pid_t child = fork();
Index: libs/libmythtv/videosource.cpp
===================================================================
--- libs/libmythtv/videosource.cpp	(revision 15101)
+++ libs/libmythtv/videosource.cpp	(working copy)
@@ -1644,6 +1644,23 @@
     };
 };
 
+class ExternalRotateCommand :
+    public LineEditSetting, public CardInputDBStorage
+{
+  public:
+    ExternalRotateCommand(const CardInput &parent) :
+        LineEditSetting(this),
+        CardInputDBStorage(this, parent, "externalcommand")
+    {
+        setLabel(QObject::tr("Antenna rotate command"));
+        setValue("");
+        setHelpText(QObject::tr("If specified, this command will be run "
+                    "before a channel change so that an antenna can be "
+                    "rotated into position. Three arguments are passed: "
+                    "frequency, MPEG program number and channel callsign."));
+    };
+};
+
 class PresetTuner : public LineEditSetting, public CardInputDBStorage
 {
   public:
@@ -1779,6 +1796,7 @@
         ConfigurationGroup *chgroup = 
             new VerticalConfigurationGroup(false, false, true, true);
         chgroup->addChild(new QuickTune(*this));
+        chgroup->addChild(new ExternalRotateCommand(*this));
         chgroup->addChild(new FreeToAir(*this));
         group->addChild(chgroup);
     }
