Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 13407)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -899,25 +899,32 @@
     activerecorder->FinishRecording();
 }
 
-void TV::AskAllowRecording(const QStringList &messages, int timeuntil,
+void TV::AskAllowRecording(const QStringList &msg, int timeuntil,
                            bool hasrec)
 {
     if (!StateIsLiveTV(GetState()))
        return;
 
-    QString title = messages[0];
-    QString chanstr = messages[1];
-    QString chansign = messages[2];
-    QString channame = messages[3];
+    ProgramInfo info;
+    QStringList::const_iterator it = msg.begin();
+    info.FromStringList(it, msg.end());
 
+    if (recorder->GetRecorderNumber() != info.cardid)
+    {
+        // Check if this is a shared tuner card,
+        // if so, then either lock mplexid or
+        // offer menu option to switch to a channel
+        // on the mplexid.
+    }
+
     QString channel = gContext->GetSetting("ChannelFormat", "<num> <sign>");
-    channel.replace("<num>", chanstr)
-        .replace("<sign>", chansign)
-        .replace("<name>", channame);
+    channel.replace("<num>", info.chanstr)
+        .replace("<sign>", info.chansign)
+        .replace("<name>", info.channame);
     
     QString message = QObject::tr(
         "MythTV wants to record \"%1\" on %2 in %3 seconds. Do you want to:")
-        .arg(title).arg(channel).arg(" %d ");
+        .arg(info.title).arg(channel).arg(" %d ");
     
     while (!GetOSD())
     {
@@ -927,13 +934,16 @@
         qApp->lock();
     }
 
+    bool is_this_rec = (recorder->GetRecorderNumber() == info.cardid);
+
     QStringList options;
-    options += tr("Record and watch while it records");
+    if (is_this_rec)
+        options += tr("Record and watch while it records");
     options += tr("Let it record and go back to the Main Menu");
     options += tr("Don't let it record, I want to watch TV");
-    int sel = (hasrec) ? 2 : 0;
+    int sel = (is_this_rec) ? ((hasrec) ? 2 : 0) : 0;
 
-    dialogname = "allowrecordingbox";
+    dialogname = (is_this_rec) ? "allowrecordingbox" : "allowrecordingbox2";
     GetOSD()->NewDialogBox(dialogname, message, options, timeuntil, sel);
 }
 
@@ -2498,10 +2508,13 @@
                             break;
                     }
                 }
-                else if (dialogname == "allowrecordingbox")
+                else if (dialogname.left(17) == "allowrecordingbox")
                 {
                     int result = GetOSD()->GetDialogResponse(dialogname);
 
+                    if ((dialogname == "allowrecordingbox2") && (result > 0))
+                        result++;
+
                     if (result == 1)
                         recorder->CancelNextRecording(false);
                     else if (result == 2)
Index: libs/libmythtv/programinfo.h
===================================================================
--- libs/libmythtv/programinfo.h	(revision 13404)
+++ libs/libmythtv/programinfo.h	(working copy)
@@ -120,8 +120,10 @@
 
     ProgramInfo& operator=(const ProgramInfo &other);
     ProgramInfo& clone(const ProgramInfo &other);
-    bool FromStringList(QStringList &list, int offset);
-    bool FromStringList(QStringList &list, QStringList::iterator &it);
+    bool FromStringList(QStringList::const_iterator &it,
+                        QStringList::const_iterator  end);
+    bool FromStringList(const QStringList &list, uint offset);
+
     bool FillInRecordInfo(const vector<ProgramInfo *> &reclist);
     
     // Destructor
Index: libs/libmythtv/remoteutil.cpp
===================================================================
--- libs/libmythtv/remoteutil.cpp	(revision 13403)
+++ libs/libmythtv/remoteutil.cpp	(working copy)
@@ -186,11 +186,11 @@
             return 0;
         }
 
-        QStringList::iterator it = strList.at(1);
+        QStringList::const_iterator it = strList.at(1);
         for (int i = 0; i < numrecordings; i++)
         {
             ProgramInfo *pginfo = new ProgramInfo();
-            pginfo->FromStringList(strList, it);
+            pginfo->FromStringList(it, strList.end());
             reclist->push_back(pginfo);
         }
     }
@@ -418,6 +418,7 @@
 
     QStringList::const_iterator it = strlist.begin();
     bool state = (*it).toInt();
+    it++;
     busy_input.FromStringList(it, strlist.end());
 
     return state;
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 13404)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -78,6 +78,68 @@
 static bool is_dishnet_eit(int cardid);
 static QString load_profile(QString,void*,ProgramInfo*,RecordingProfile&);
 
+uint RemoteGetFlags(uint cardid)
+{
+    if (gContext->IsBackend())
+    {
+        const TVRec *rec = TVRec::GetTVRec(cardid);
+        if (rec)
+            return rec->GetFlags();
+    }
+
+    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
+    strlist << "GET_FLAGS";
+    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
+        return 0;
+
+    return strlist[0].toInt();
+}
+
+bool RemoteRecordPending(uint cardid, const ProgramInfo *pginfo,
+                         uint secsleft)
+{
+    if (gContext->IsBackend())
+    {
+        TVRec *rec = TVRec::GetTVRec(cardid);
+        if (rec)
+        {
+            rec->RecordPending(pginfo, secsleft);
+            return true;
+        }
+    }
+
+    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
+    strlist << "RECORD_PENDING";
+    strlist << QString::number(secsleft);
+    pginfo->ToStringList(strlist);
+
+    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
+        return false;
+
+    return strlist[0] == "OK";
+}
+
+bool RemoteStopRecording(uint cardid)
+{
+    if (gContext->IsBackend())
+    {
+        TVRec *rec = TVRec::GetTVRec(cardid);
+        if (rec)
+        {
+            rec->StopRecording();
+            return true;
+        }
+    }
+
+    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
+    strlist << "STOP_RECORDING";
+
+    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
+        return false;
+
+    return strlist[0] == "OK";
+}
+
 /** \class TVRec
  *  \brief This is the coordinating class of the \ref recorder_subsystem.
  *
@@ -362,19 +424,65 @@
  *   it. Depending on what that query returns, the recording will be
  *   started or not started.
  *
- *  \sa TV::AskAllowRecording(const QStringList&, int)
+ *  \sa TV::AskAllowRecording(const QStringList&, int, bool)
  *  \param rcinfo   ProgramInfo on pending program.
  *  \param secsleft Seconds left until pending recording begins.
  */
 void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft)
 {
     QMutexLocker lock(&stateChangeLock);
+
+    uint inputid = rcinfo->inputid;
+    cout<<endl;
+    VERBOSE(VB_RECORD, LOC +
+            QString("RecordPending on inputid %1").arg(inputid));
+
     if (pendingRecording)
         delete pendingRecording;
 
     pendingRecording = new ProgramInfo(*rcinfo);
     recordPendingStart = QDateTime::currentDateTime().addSecs(secsleft);
     SetFlags(kFlagAskAllowRecording);
+
+    if (rcinfo->cardid != cardid)
+        return;
+
+    // We also need to check our input groups
+    vector<uint> inputgroupids = CardUtil::GetInputGroups(inputid);
+
+    for (uint i = 0; i < inputgroupids.size(); i++)
+    {
+        VERBOSE(VB_RECORD, LOC +
+                QString("  Group ID %1").arg(inputgroupids[i]));
+    }
+
+    vector<uint> cardids;
+    for (uint i = 0; i < inputgroupids.size(); i++)
+    {
+        vector<uint> tmp = CardUtil::GetGroupCardIDs(inputgroupids[i]);
+        for (uint j = 0; j < tmp.size(); j++)
+        {
+            if (tmp[j] == (uint) cardid)
+                continue;
+
+            if (find(cardids.begin(), cardids.end(), tmp[j]) != cardids.end())
+                continue;
+
+            cardids.push_back(tmp[j]);
+        }
+    }
+
+    for (uint i = 0; i < cardids.size(); i++)
+        VERBOSE(VB_RECORD, LOC + QString("  Card ID %1").arg(cardids[i]));
+
+    pendingRecordingCardIds = cardids;
+
+    stateChangeLock.unlock();
+    for (uint i = 0; i < cardids.size(); i++)
+        RemoteRecordPending(cardids[i], rcinfo, secsleft);
+    stateChangeLock.lock();
+
+    cout<<endl;
 }
 
 /** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*)
@@ -467,6 +575,43 @@
     // Flush out events...
     WaitForEventThreadSleep();
 
+    // If the needed input is in a shared input group, and we are
+    // not canceling the recording anyway, check other recorders
+    if (pendingRecording && pendingRecordingCardIds.size())
+    {
+        cout<<endl;
+        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin");
+        vector<uint> &cardids = pendingRecordingCardIds;
+
+        // If any LiveTV session decided to cancel recording, don't record
+        for (uint i = 0; i < cardids.size(); i++)
+        {
+            uint flags = RemoteGetFlags(cardids[i]);
+            if (flags & kFlagCancelNextRecording)
+            {
+                SetFlags(kFlagCancelNextRecording);
+                break;
+            }
+        }
+
+        // Stop all the remote recordings
+        uint maxi = HasFlags(kFlagCancelNextRecording) ? cardids.size() : 0;
+        bool ok = true;
+        for (uint i = 0; (i < maxi) && ok; i++)
+        {
+            VERBOSE(VB_RECORD, LOC + QString("Attempting to stop card %1")
+                    .arg(cardids[i]));
+            ok &= RemoteStopRecording(cardids[i]);
+        }
+
+        cardids.clear();
+
+        // If we failed to stop the remote recordings, don't record
+        if (!ok)
+            SetFlags(kFlagCancelNextRecording);
+        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - done\n");
+    }
+
     // If in post-roll, end recording
     if (GetState() == kState_RecordingOnly &&
         !HasFlags(kFlagCancelNextRecording))
@@ -476,7 +621,8 @@
         stateChangeLock.lock();
     }
 
-    if (internalState == kState_None)
+    if (!HasFlags(kFlagCancelNextRecording) &&
+        (GetState() == kState_None))
     {
         if (tvchain)
         {
@@ -1215,12 +1361,10 @@
                     .arg(cardid).arg(timeuntil)
                     .arg(pseudoLiveTVRecording ? 1 : 0);
                 VERBOSE(VB_IMPORTANT, LOC + query);
-                QStringList messages;
-                messages << pendingRecording->title
-                         << pendingRecording->chanstr
-                         << pendingRecording->chansign
-                         << pendingRecording->channame;
-                MythEvent me(query, messages);
+
+                QStringList msg;
+                pendingRecording->ToStringList(msg);
+                MythEvent me(query, msg);
                 gContext->dispatch(me);
             }
         }
Index: libs/libmythtv/programinfo.cpp
===================================================================
--- libs/libmythtv/programinfo.cpp	(revision 13404)
+++ libs/libmythtv/programinfo.cpp	(working copy)
@@ -275,8 +275,8 @@
 /** \fn ProgramInfo::ToStringList(QStringList&) const
  *  \brief Serializes ProgramInfo into a QStringList which can be passed
  *         over a socket.
- *  \sa FromStringList(QStringList&,int),
- *      FromStringList(QStringList&,QStringList::iterator&)
+ *  \sa FromStringList(QStringList::const_iterator&,
+                       QStringList::const_iterator)
  */
 void ProgramInfo::ToStringList(QStringList &list) const
 {
@@ -327,19 +327,25 @@
     STR_TO_LIST((storagegroup != "") ? storagegroup : "Default")
 }
 
-/** \fn ProgramInfo::FromStringList(QStringList&,int)
+/** \fn ProgramInfo::FromStringList(const QStringList&,uint)
  *  \brief Uses a QStringList to initialize this ProgramInfo instance.
+ *
+ *  This is a convenience method which calls FromStringList(
+    QStringList::const_iterator&,QStringList::const_iterator)
+ *  with an iterator created using list.at(offset).
+ *
  *  \param list   QStringList containing serialized ProgramInfo.
  *  \param offset First field in list to treat as beginning of
  *                serialized ProgramInfo.
  *  \return true if it succeeds, false if it fails.
- *  \sa ToStringList(QStringList&),
- *      FromStringList(QStringList&,QStringList::iterator&)
+ *  \sa FromStringList(QStringList::const_iterator&,
+                       QStringList::const_iterator)
+ *      ToStringList(QStringList&) const
  */
-bool ProgramInfo::FromStringList(QStringList &list, int offset)
+bool ProgramInfo::FromStringList(const QStringList &list, uint offset)
 {
-    QStringList::iterator it = list.at(offset);
-    return FromStringList(list, it);
+    QStringList::const_iterator it = list.at(offset);
+    return FromStringList(it, list.end());
 }
 
 #define NEXT_STR()             if (it == listend)     \
@@ -365,18 +371,21 @@
 
 #define FLOAT_FROM_LIST(x)     NEXT_STR() (x) = atof(ts.ascii());
 
-/** \fn ProgramInfo::FromStringList(QStringList&,QStringList::iterator&)
+/** \fn ProgramInfo::FromStringList(QStringList::const_iterator&,
+                                    QStringList::const_iterator)
  *  \brief Uses a QStringList to initialize this ProgramInfo instance.
- *  \param list   QStringList containing serialized ProgramInfo.
- *  \param it     Iterator pointing to first field in list to treat as
+ *  \param beg    Iterator pointing to first item in list to treat as
  *                beginning of serialized ProgramInfo.
+ *  \param end    Iterator that will stop parsing of the ProgramInfo
  *  \return true if it succeeds, false if it fails.
- *  \sa ToStringList(QStringList&), FromStringList(QStringList&,int)
+ *  \sa FromStringList(const QStringList&,uint)
+ *      ToStringList(QStringList&) const
  */
-bool ProgramInfo::FromStringList(QStringList &list, QStringList::iterator &it)
+
+bool ProgramInfo::FromStringList(QStringList::const_iterator &it,
+                                 QStringList::const_iterator  listend)
 {
-    const char* listerror = LOC + "FromStringList, not enough items in list.\n"; 
-    QStringList::iterator listend = list.end();
+    QString listerror = LOC + "FromStringList, not enough items in list."; 
     QString ts;
     int ti;
 
@@ -4476,12 +4485,12 @@
     hasConflicts = slist[0].toInt();
 
     bool result = true;
-    QStringList::Iterator sit = slist.at(2);
+    QStringList::const_iterator sit = slist.at(2);
 
     while (result && sit != slist.end())
     {
         ProgramInfo *p = new ProgramInfo();
-        result = p->FromStringList(slist, sit);
+        result = p->FromStringList(sit, slist.end());
         if (result)
             append(p);
         else
Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h	(revision 13396)
+++ libs/libmythtv/tv_rec.h	(working copy)
@@ -223,6 +223,8 @@
 
     void SetNextLiveTVDir(QString dir);
 
+    uint GetFlags(void) const { return stateFlags; }
+
     static TVRec *GetTVRec(uint cardid);
 
   public slots:
@@ -364,6 +366,7 @@
     // Pending recording info
     ProgramInfo *pendingRecording;
     QDateTime    recordPendingStart;
+    vector<uint> pendingRecordingCardIds;
 
     // Pseudo LiveTV recording
     ProgramInfo *pseudoLiveTVRecording;
@@ -378,7 +381,6 @@
     RingBuffer  *ringBuffer;
     QString      rbFileExt;
 
-  public:
     static QMutex            cardsLock;
     static QMap<uint,TVRec*> cards;
 
Index: programs/mythbackend/encoderlink.h
===================================================================
--- programs/mythbackend/encoderlink.h	(revision 13396)
+++ programs/mythbackend/encoderlink.h	(working copy)
@@ -54,6 +54,7 @@
     bool IsBusyRecording(void);
 
     TVState GetState();
+    uint GetFlags(void) const;
     bool IsRecording(const ProgramInfo *rec); // scheduler call only.
 
     bool MatchesRecording(const ProgramInfo *rec);
Index: programs/mythbackend/mainserver.cpp
===================================================================
--- programs/mythbackend/mainserver.cpp	(revision 13396)
+++ programs/mythbackend/mainserver.cpp	(working copy)
@@ -937,10 +937,10 @@
         {
             ProgramInfo pinfo;
             ProgramList slavelist;
-            QStringList::Iterator sit = slist.at(1);
+            QStringList::const_iterator sit = slist.at(1);
             while (sit != slist.end())
             {
-                if (!pinfo.FromStringList(slist, sit))
+                if (!pinfo.FromStringList(sit, slist.end()))
                     break;
                 slavelist.append(new ProgramInfo(pinfo));
             }
@@ -3084,8 +3084,12 @@
     {
         retlist << QString::number((int)enc->GetState());
     }
-    if (command == "IS_BUSY")
+    else if (command == "GET_FLAGS")
     {
+        retlist << QString::number(enc->GetFlags());
+    }
+    else if (command == "IS_BUSY")
+    {
         TunedInputInfo busy_input;
         retlist << QString::number((int)enc->IsBusy(&busy_input));
         busy_input.ToStringList(retlist);
@@ -3119,6 +3123,11 @@
         retlist << "OK";
         delete pginfo;
     }
+    else if (command == "STOP_RECORDING")
+    {
+        enc->StopRecording();
+        retlist << "OK";
+    }
     else if (command == "GET_MAX_BITRATE")
     {
         long long value = enc->GetMaxBitrate();
Index: programs/mythbackend/encoderlink.cpp
===================================================================
--- programs/mythbackend/encoderlink.cpp	(revision 13396)
+++ programs/mythbackend/encoderlink.cpp	(working copy)
@@ -15,6 +15,9 @@
 #include "previewgenerator.h"
 #include "storagegroup.h"
 
+#define LOC QString("EncoderLink(%1): ").arg(m_capturecardnum)
+#define LOC_ERR QString("EncoderLink(%1) Error: ").arg(m_capturecardnum)
+
 /**
  * \class EncoderLink
  * \brief Provides an interface to both local and remote TVRec's for the mythbackend.
@@ -143,6 +146,27 @@
     return retval;
 }
 
+/** \fn EncoderLink::GetFlags(void) const
+ *  \brief Returns the flag state of the recorder.
+ *  \sa TVRec::GetFlags(void) const, \ref recorder_subsystem
+ */
+uint EncoderLink::GetFlags(void) const
+{
+    uint retval = 0;
+
+    if (!IsConnected())
+        return retval;
+
+    if (local)
+        retval = tv->GetFlags();
+    else if (sock)
+        retval = sock->GetEncoderState(m_capturecardnum);
+    else
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "GetFlags failed");
+
+    return retval;
+}
+
 /** \fn EncoderLink::IsRecording(const ProgramInfo *rec)
  *  \brief Returns true if rec is scheduled for recording.
  *  \param rec Recording to check.
