Index: libs/libmythtv/osd.h
===================================================================
--- libs/libmythtv/osd.h	(revision 8514)
+++ libs/libmythtv/osd.h	(working copy)
@@ -77,7 +77,7 @@
     void SetSettingsText(const QString &text, int length);
 
     void NewDialogBox(const QString &name, const QString &message, 
-                      QStringList &options, int length);
+                      QStringList &options, int length, int sel = 0);
     void DialogUp(const QString &name);
     void DialogDown(const QString &name);
     bool DialogShowing(const QString &name);
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 8514)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -246,6 +246,7 @@
       // Program Info for currently playing video
       recorderPlaybackInfo(NULL),
       playbackinfo(NULL), inputFilename(""), playbackLen(0),
+      lastProgram(NULL), jumpToProgram(false),
       // Video Players
       nvp(NULL), pipnvp(NULL), activenvp(NULL),
       // Remote Encoders
@@ -262,6 +263,12 @@
       // Window info (GUI is optional, transcoding, preview img, etc)
       myWindow(NULL), embedWinID(0), embedBounds(0,0,0,0)
 {
+    for (uint i = 0; i < 2; i++)
+    {
+        pseudoLiveTVRec[i]   = NULL;
+        pseudoLiveTVState[i] = kPseudoNormalLiveTV;
+    }
+
     lastLcdUpdate = QDateTime::currentDateTime();
     lastLcdUpdate.addYears(-1); // make last LCD update last year..
     lastSignalMsgTime.start();
@@ -335,11 +342,11 @@
             float wmult, hmult;
             gContext->GetScreenSettings(xbase, width, wmult,
                                         ybase, height, hmult);
-            if (abs(saved_gui_bounds.x()-xbase < 3) &&
-                abs(saved_gui_bounds.y()-ybase < 3))
+            if ((abs(saved_gui_bounds.x()-xbase) < 3) &&
+                (abs(saved_gui_bounds.y()-ybase) < 3))
             {
-                saved_gui_bounds.setX(xbase);
-                saved_gui_bounds.setY(ybase);
+                saved_gui_bounds = QRect(QPoint(xbase, ybase),
+                                         mainWindow->size());
             }
         }
 
@@ -574,7 +581,8 @@
     activerecorder->FinishRecording();
 }
 
-void TV::AskAllowRecording(const QStringList &messages, int timeuntil)
+void TV::AskAllowRecording(const QStringList &messages, int timeuntil,
+                           bool hasrec)
 {
     if (!StateIsLiveTV(GetState()))
        return;
@@ -605,9 +613,10 @@
     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;
 
     dialogname = "allowrecordingbox";
-    GetOSD()->NewDialogBox(dialogname, message, options, timeuntil); 
+    GetOSD()->NewDialogBox(dialogname, message, options, timeuntil, sel);
 }
 
 void TV::setLastProgram(ProgramInfo *rcinfo)
@@ -1489,6 +1498,29 @@
             exitPlayer = false;
         }
 
+        for (uint i = InStateChange() ? 2 : 0; i < 2; i++)
+        {
+            if (kPseudoChangeChannel != pseudoLiveTVState[i])
+                continue;
+
+            VERBOSE(VB_PLAYBACK, "REC_PROGRAM -- channel change "<<i);
+            if (activerecorder != recorder)
+                ToggleActiveWindow();
+
+            uint    chanid  = pseudoLiveTVRec[i]->chanid.toUInt();
+            QString channum = pseudoLiveTVRec[i]->chanstr;
+            str_vec_t tmp = prevChan;
+            prevChan.clear();
+            if (i && activenvp == nvp)
+                ToggleActiveWindow();
+            ChangeChannel(chanid, channum);
+            prevChan = tmp;
+            pseudoLiveTVState[i] = kPseudoRecording;
+
+            if (i && pipnvp)
+                TogglePIPView();
+        }
+
         if ((doing_ff_rew || speed_index) && 
             activenvp && activenvp->AtNormalSpeed())
         {
@@ -1848,11 +1880,13 @@
                 else if (dialogname == "allowrecordingbox")
                 {
                     int result = GetOSD()->GetDialogResponse(dialogname);
-    
-                    if (result == 2)
+
+                    if (result == 1)
+                        recorder->CancelNextRecording(false);
+                    else if (result == 2)
                         StopLiveTV();
                     else if (result == 3)
-                        recorder->CancelNextRecording();
+                        recorder->CancelNextRecording(true);
                 }
                 else if (dialogname == "channel_timed_out")
                 {
@@ -2212,7 +2246,6 @@
             }
             else if (StateIsLiveTV(GetState()))
             {
-                ChangeState(kState_None);
                 exitPlayer = true;
                 wantsToQuit = true;
             }
@@ -2292,7 +2325,7 @@
         }
     }
 
-    if (StateIsLiveTV(GetState()))
+    if (StateIsLiveTV(GetState()) || StateIsPlaying(internalState))
     {
         for (unsigned int i = 0; i < actions.size() && !handled; i++)
         {
@@ -2306,32 +2339,52 @@
                 else
                     ToggleOSD(true);
             }
-            else if (action == "CHANNELUP")
-            {
-                if (persistentbrowsemode)
-                    BrowseDispInfo(BROWSE_UP);
-                else
-                    ChangeChannel(CHANNEL_DIRECTION_UP);
-            }
-            else if (action == "CHANNELDOWN")
-            {
-                if (persistentbrowsemode)
-                    BrowseDispInfo(BROWSE_DOWN);
-                else
-                    ChangeChannel(CHANNEL_DIRECTION_DOWN);
-            }
-            else if (action == "TOGGLERECORD")
+            else if (action == "TOGGLESLEEP")
+                ToggleSleepTimer();
+            else
+                handled = false;
+        }
+    }
+
+    uint aindx = (activenvp == nvp) ? 0 : 1;
+    if (StateIsLiveTV(GetState()))
+    {
+        for (unsigned int i = 0; i < actions.size() && !handled; i++)
+        {
+            QString action = actions[i];
+            handled = true;
+
+            if (action == "TOGGLERECORD")
                 ToggleRecord();
-            else if (action == "NEXTFAV")
-                ChangeChannel(CHANNEL_DIRECTION_FAVORITE);
             else if (action == "TOGGLEFAV")
                 ToggleChannelFavorite();
+            else if (action == "SELECT")
+                CommitQueuedInput();
+            else if (action == "TOGGLERECCONTROLS")
+                DoToggleRecPictureAttribute();
+            else if (action == "TOGGLEBROWSE" && pseudoLiveTVState[aindx])
+                ShowOSDTreeMenu();
+            else
+                handled = false;
+        }
+
+        if (redisplayBrowseInfo)
+            BrowseStart();
+    }
+
+    if (StateIsLiveTV(GetState()) && !pseudoLiveTVState[aindx])
+    {
+        for (unsigned int i = 0; i < actions.size() && !handled; i++)
+        {
+            QString action = actions[i];
+            handled = true;
+
+            if (action == "NEXTFAV")
+                ChangeChannel(CHANNEL_DIRECTION_FAVORITE);
             else if (action == "TOGGLEINPUTS")
                 ToggleInputs();
             else if (action == "SWITCHCARDS")
                 SwitchCards();
-            else if (action == "SELECT")
-                CommitQueuedInput();
             else if (action == "GUIDE")
                 LoadMenu();
             else if (action == "TOGGLEPIPMODE")
@@ -2340,14 +2393,24 @@
                 ToggleActiveWindow();
             else if (action == "SWAPPIP")
                 SwapPIP();
-            else if (action == "TOGGLERECCONTROLS")
-                DoToggleRecPictureAttribute();
             else if (action == "TOGGLEBROWSE")
                 BrowseStart();
             else if (action == "PREVCHAN")
                 PreviousChannel();
-            else if (action == "TOGGLESLEEP")
-                ToggleSleepTimer();
+            else if (action == "CHANNELUP")
+            {
+                if (persistentbrowsemode)
+                    BrowseDispInfo(BROWSE_UP);
+                else
+                    ChangeChannel(CHANNEL_DIRECTION_UP);
+            }
+            else if (action == "CHANNELDOWN")
+            {
+                if (persistentbrowsemode)
+                    BrowseDispInfo(BROWSE_DOWN);
+                else
+                    ChangeChannel(CHANNEL_DIRECTION_DOWN);
+            }
             else
                 handled = false;
         }
@@ -2362,15 +2425,8 @@
             QString action = actions[i];
             handled = true;
 
-            if (action == "INFO")
+            if (action == "SELECT")
             {
-                if (HasQueuedInput())
-                    DoArbSeek(ARBSEEK_SET);
-                else
-                    ToggleOSD(true);
-            }
-            else if (action == "SELECT")
-            {
                 if (!was_doing_ff_rew)
                 {
                     if (gContext->GetNumSetting("AltClearSavedPosition", 1)
@@ -2422,8 +2478,6 @@
                     DoSeek(jumptime * 60, tr("Jump Ahead"));
                 }
             }
-            else if (action == "TOGGLESLEEP")
-                ToggleSleepTimer();
             else
                 handled = false;
         }
@@ -2485,6 +2539,8 @@
             else
             {
                 VERBOSE(VB_IMPORTANT, LOC_ERR + "PiP player failed to start");
+                delete pipnvp;
+                pipnvp = NULL;
                 TeardownPipPlayer();
             }
         }
@@ -2513,6 +2569,8 @@
         piprecorder->StopLiveTV();
 
         TeardownPipPlayer();
+
+        SetPseudoLiveTV(1, NULL, kPseudoNormalLiveTV);
     }
 }
 
@@ -3313,7 +3371,8 @@
         if (HasQueuedInput())
             DoArbSeek(ARBSEEK_FORWARD);
     }
-    else if (StateIsLiveTV(GetState()))
+    else if (StateIsLiveTV(GetState()) &&
+             !pseudoLiveTVState[(activenvp == nvp) ? 0 : 1])
     {
         QString channum = GetQueuedChanNum();
         if (browsemode)
@@ -3322,9 +3381,10 @@
             if (activenvp == nvp && GetOSD())
                 GetOSD()->HideSet("channel_number");
         }
-        else if (activerecorder->CheckChannel(channum))
+        else if (GetQueuedChanID() ||
+                 (!channum.isEmpty() && activerecorder->CheckChannel(channum)))
             ChangeChannel(GetQueuedChanID(), channum);
-        else if (GetQueuedInput() != "")
+        else if (!GetQueuedInput().isEmpty())
             ChangeChannel(GetQueuedChanID(), GetQueuedInput());
     }
 
@@ -4368,12 +4428,20 @@
             QStringList tokens = QStringList::split(" ", message);
             int cardnum = tokens[1].toInt();
             int timeuntil = tokens[2].toInt();
+            int hasrec    = tokens[3].toInt();
+            VERBOSE(VB_IMPORTANT, LOC + message << " hasrec: "<<hasrec);
 
             if (cardnum == recorder->GetRecorderNumber())
             {
                 menurunning = false;
-                AskAllowRecording(me->ExtraDataList(), timeuntil);
+                AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec);
             }
+            else if (piprecorder &&
+                     cardnum == piprecorder->GetRecorderNumber())
+            {
+                VERBOSE(VB_GENERAL, LOC + "Disabling PiP for recording");
+                TogglePIPView();
+            }
         }
         else if (recorder && message.left(11) == "QUIT_LIVETV")
         {
@@ -4387,7 +4455,40 @@
                 wantsToQuit = false;
                 exitPlayer = true;
             }
+            else if (piprecorder &&
+                     cardnum == piprecorder->GetRecorderNumber())
+            {
+                VERBOSE(VB_GENERAL, LOC + "Disabling PiP for QUIT_LIVETV");
+                TogglePIPView();
+            }
         }
+        else if (recorder && message.left(12) == "LIVETV_WATCH")
+        {
+            message = message.simplifyWhiteSpace();
+            QStringList tokens = QStringList::split(" ", message);
+            int cardnum = tokens[1].toInt();
+            int watch   = tokens[2].toInt();
+
+            uint s = (cardnum == recorder->GetRecorderNumber()) ? 0 : 1;
+
+            if (cardnum == recorder->GetRecorderNumber() ||
+                (piprecorder && cardnum == piprecorder->GetRecorderNumber()))
+            {
+                if (watch)
+                {
+                    ProgramInfo *pi = new ProgramInfo();
+                    QStringList list = me->ExtraDataList();
+                    if (pi->FromStringList(list, 0))
+                        SetPseudoLiveTV(s, pi, kPseudoChangeChannel);
+                    delete pi;
+
+                    if (!s && pipnvp)
+                        TogglePIPView();
+                }
+                else
+                    SetPseudoLiveTV(s, NULL, kPseudoNormalLiveTV);
+            }
+        }
         else if (tvchain && message.left(12) == "LIVETV_CHAIN")
         {
             message = message.simplifyWhiteSpace();
@@ -4575,6 +4676,35 @@
     delete program_info;
 }
 
+void TV::SetPseudoLiveTV(uint i, const ProgramInfo *pi, PseudoState new_state)
+{
+    ProgramInfo *old_rec = pseudoLiveTVRec[i];
+    ProgramInfo *new_rec = NULL;
+
+    if (pi)
+    {
+        new_rec = new ProgramInfo(*pi);
+        QString msg = QString("Wants to record: %1 %2 %3 %4")
+            .arg(new_rec->title).arg(new_rec->chanstr)
+            .arg(new_rec->recstartts.toString())
+            .arg(new_rec->recendts.toString());
+        VERBOSE(VB_PLAYBACK, LOC + msg);
+    }
+
+    pseudoLiveTVRec[i]   = new_rec;
+    pseudoLiveTVState[i] = new_state;
+
+    if (old_rec)
+    {
+        QString msg = QString("Done to recording: %1 %2 %3 %4")
+            .arg(old_rec->title).arg(old_rec->chanstr)
+            .arg(old_rec->recstartts.toString())
+            .arg(old_rec->recendts.toString());
+        VERBOSE(VB_PLAYBACK, LOC + msg);        
+        delete old_rec;
+    }
+}
+
 void TV::ToggleRecord(void)
 {
     if (browsemode)
@@ -4609,18 +4739,23 @@
     }
 
     QString cmdmsg("");
+    uint s = (activenvp == nvp) ? 0 : 1;
     if (playbackinfo->GetAutoExpireFromRecorded() == kLiveTVAutoExpire)
     {
         int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0);
         playbackinfo->SetAutoExpire(autoexpiredef);
         playbackinfo->ApplyRecordRecGroupChange("Default");
         cmdmsg = tr("Record");
+        SetPseudoLiveTV(s, playbackinfo, kPseudoRecording);
+        VERBOSE(VB_RECORD, LOC + "Toggling Record on");
     }
     else
     {
         playbackinfo->SetAutoExpire(kLiveTVAutoExpire);
         playbackinfo->ApplyRecordRecGroupChange("LiveTV");
         cmdmsg = tr("Cancel Record");
+        SetPseudoLiveTV(s, playbackinfo, kPseudoNormalLiveTV);
+        VERBOSE(VB_RECORD, LOC + "Toggling Record off");
     }
 
     QString msg = cmdmsg + "\"" + playbackinfo->title + "\"";
Index: libs/libmythtv/remoteencoder.h
===================================================================
--- libs/libmythtv/remoteencoder.h	(revision 8514)
+++ libs/libmythtv/remoteencoder.h	(working copy)
@@ -36,7 +36,7 @@
     void PauseRecorder(void);
     void FinishRecording(void);
     void FrontendReady(void);
-    void CancelNextRecording(void);
+    void CancelNextRecording(bool cancel);
 
     void ToggleInputs(void);
     int ChangeContrast(bool direction);
Index: libs/libmythtv/tv_play.h
===================================================================
--- libs/libmythtv/tv_play.h	(revision 8514)
+++ libs/libmythtv/tv_play.h	(working copy)
@@ -53,6 +53,13 @@
     }
 };
 
+typedef enum
+{
+    kPseudoNormalLiveTV  = 0,
+    kPseudoChangeChannel = 1,
+    kPseudoRecording     = 2,
+} PseudoState;
+
 class TV : public QObject
 {
     Q_OBJECT
@@ -97,7 +104,7 @@
     // Various commands
     void ShowNoRecorderDialog(void);
     void FinishRecording(void);
-    void AskAllowRecording(const QStringList &messages, int timeuntil);
+    void AskAllowRecording(const QStringList&, int, bool);
 
     // Boolean queries
 
@@ -302,6 +309,8 @@
 
     void GetPlayGroupSettings(const QString &group);
 
+    void SetPseudoLiveTV(uint, const ProgramInfo*, PseudoState);
+
     static QStringList GetValidRecorderList(uint chanid);
     static QStringList GetValidRecorderList(const QString &channum);
     static QStringList GetValidRecorderList(uint, const QString&);
@@ -442,6 +451,10 @@
     ProgramInfo *lastProgram;   ///< last program played with this player
     bool         jumpToProgram;
 
+    // Recording to play next, after LiveTV
+    ProgramInfo *pseudoLiveTVRec[2];
+    PseudoState  pseudoLiveTVState[2];
+
     // Video Players
     NuppelVideoPlayer *nvp;
     NuppelVideoPlayer *pipnvp;
Index: libs/libmythtv/remoteencoder.cpp
===================================================================
--- libs/libmythtv/remoteencoder.cpp	(revision 8514)
+++ libs/libmythtv/remoteencoder.cpp	(working copy)
@@ -227,12 +227,11 @@
     }
 }
 
-void RemoteEncoder::CancelNextRecording(void)
+void RemoteEncoder::CancelNextRecording(bool cancel)
 {
     QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
     strlist << "CANCEL_NEXT_RECORDING";
-    VERBOSE(VB_IMPORTANT, QString("Sending QUERY_RECORDER %1 - CANCEL_NEXT_RECORDING")
-                          .arg(recordernum));
+    strlist << QString::number((cancel) ? 1 : 0);
                           
     SendReceiveStringList(strlist);
 }
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 8514)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -120,6 +120,8 @@
       curRecording(NULL), autoRunJobs(JOB_NONE),
       // Pending recording info
       pendingRecording(NULL),
+      // Pseudo LiveTV recording
+      pseudoLiveTVRecording(NULL),
       // tvchain
       tvchain(NULL),
       // RingBuffer info
@@ -348,6 +350,40 @@
     SetFlags(kFlagAskAllowRecording);
 }
 
+/** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*)
+ *  \brief Sets the pseudo LiveTV ProgramInfo
+ */
+void TVRec::SetPseudoLiveTVRecording(ProgramInfo *pi)
+{
+    ProgramInfo *old_rec = pseudoLiveTVRecording;
+    pseudoLiveTVRecording = pi;
+    if (old_rec)
+        delete old_rec;
+}
+
+/** \fn TVRec::GetRecordEndTime(const ProgramInfo*) const
+ *  \brief Returns recording end time with proper post-roll
+ */
+QDateTime TVRec::GetRecordEndTime(const ProgramInfo *pi) const
+{
+    bool spcat = (pi->category == overRecordCategory);
+    int secs = (spcat) ? overRecordSecCat : overRecordSecNrml;
+    return pi->recendts.addSecs(secs);
+}
+
+/** \fn TVRec::CancelNextRecording(bool)
+ *  \brief Tells TVRec to cancel the upcoming recording.
+ *  \sa RecordPending(const ProgramInfo*,int),
+ *      TV::AskAllowRecording(const QStringList&,int)
+ */
+void TVRec::CancelNextRecording(bool cancel)
+{
+    if (cancel)
+        SetFlags(kFlagCancelNextRecording);
+    else
+        ClearFlags(kFlagCancelNextRecording);
+}
+
 /** \fn TVRec::StartRecording(const ProgramInfo*)
  *  \brief Tells TVRec to Start recording the program "rcinfo"
  *         as soon as possible.
@@ -409,48 +445,14 @@
     WaitForEventThreadSleep();
 
     // If in post-roll, end recording
-    if (GetState() == kState_RecordingOnly)
+    if (GetState() == kState_RecordingOnly &&
+        !HasFlags(kFlagCancelNextRecording))
     {
         stateChangeLock.unlock();
         StopRecording();
         stateChangeLock.lock();
     }
 
-    // Request tuner from Live TV instance
-    if (internalState == kState_WatchingLiveTV && 
-        !HasFlags(kFlagCancelNextRecording))
-    {
-        QString message = QString("QUIT_LIVETV %1").arg(cardid);
-        MythEvent me(message);
-        gContext->dispatch(me);
-
-        MythTimer timer;
-        timer.start();
-
-        // Wait at least 10 seconds for response
-        while ((internalState != kState_None) && timer.elapsed() < 10000)
-            WaitForEventThreadSleep(false, max(10000 - timer.elapsed(), 100));
-
-        // Try again
-        if (internalState != kState_None)
-        {
-            gContext->dispatch(me);
-
-            timer.restart();
-            // Wait at least 10 seconds for response
-            while ((internalState != kState_None) && timer.elapsed() < 10000)
-                WaitForEventThreadSleep(
-                    false, max(10000 - timer.elapsed(), 100));
-        }
-
-        // Try harder
-        if (internalState != kState_None)
-        {
-            SetFlags(kFlagExitPlayer);
-            WaitForEventThreadSleep();
-        }
-    }
-
     if (internalState == kState_None)
     {
         if (tvchain)
@@ -461,10 +463,7 @@
             tvchain = NULL;
         }
 
-        // Add post-roll to new recording end time.
-        bool spcat = (rcinfo->category == overRecordCategory);
-        int secs = (spcat) ? overRecordSecCat : overRecordSecNrml;
-        recordEndTime = rcinfo->recendts.addSecs(secs);
+        recordEndTime = GetRecordEndTime(rcinfo);
 
         // Tell event loop to begin recording.
         curRecording = new ProgramInfo(*rcinfo);
@@ -475,6 +474,23 @@
 
         retval = rsRecording;
     }
+    else if (!HasFlags(kFlagCancelNextRecording) &&
+             (GetState() == kState_WatchingLiveTV))
+    {
+        SetPseudoLiveTVRecording(new ProgramInfo(*rcinfo));
+        recordEndTime = GetRecordEndTime(rcinfo);
+
+        // We want the frontend to to change channel for recording
+        // and disable the UI for channel change, PiP, etc.
+
+        QString message = QString("LIVETV_WATCH %1 1").arg(cardid);
+        QStringList prog;
+        rcinfo->ToStringList(prog);
+        MythEvent me(message, prog);
+        gContext->dispatch(me);
+
+        retval = rsRecording;
+    }
     else if (!HasFlags(kFlagCancelNextRecording))
     {
         msg = QString("Wanted to record: %1 %2 %3 %4\n"
@@ -493,8 +509,6 @@
         retval = rsTunerBusy;
     }
 
-    ClearFlags(kFlagCancelNextRecording);
-
     WaitForEventThreadSleep();
 
     return retval;
@@ -512,6 +526,7 @@
         ChangeState(RemoveRecording(GetState()));
         // wait for state change to take effect
         WaitForEventThreadSleep();
+        ClearFlags(kFlagCancelNextRecording);
     }
 }
 
@@ -675,6 +690,12 @@
         tuningRequests.enqueue(TuningRequest(kFlagKillRec|kFlagKillRingBuffer));
         SET_NEXT();
     }
+    else if (TRANSITION(kState_WatchingLiveTV, kState_RecordingOnly))
+    {
+        SetPseudoLiveTVRecording(NULL);
+
+        SET_NEXT();
+    }
     else if (TRANSITION(kState_None, kState_RecordingOnly))
     {
         tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording));
@@ -1135,25 +1156,31 @@
 
         // If we have a pending recording and AskAllowRecording is set
         // and the frontend is ready send an ASK_RECORDING query to frontend.
-        if (pendingRecording &&
-            HasFlags(kFlagAskAllowRecording | kFlagFrontendReady))
+        if (pendingRecording && HasFlags(kFlagAskAllowRecording))
         {
             ClearFlags(kFlagAskAllowRecording);
 
-            int timeuntil = QDateTime::currentDateTime()
-                .secsTo(recordPendingStart);
+            CheckForRecGroupChange();
+            if (pseudoLiveTVRecording)
+                SetFlags(kFlagCancelNextRecording);
 
-            QString query = QString("ASK_RECORDING %1 %2")
-                .arg(cardid).arg(timeuntil);
-            QStringList messages;
-            messages << pendingRecording->title
-                     << pendingRecording->chanstr
-                     << pendingRecording->chansign
-                     << pendingRecording->channame;
-            
-            MythEvent me(query, messages);
+            if (GetState() == kState_WatchingLiveTV)
+            {
+                int timeuntil = QDateTime::currentDateTime()
+                    .secsTo(recordPendingStart);
 
-            gContext->dispatch(me);
+                QString query = QString("ASK_RECORDING %1 %2 %3")
+                    .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);
+                gContext->dispatch(me);
+            }
         }
 
         // If we are recording a program, check if the recording is
@@ -1169,11 +1196,38 @@
         if (curRecording)
             curRecording->UpdateInUseMark();
 
-        if (GetState() == kState_WatchingLiveTV && curRecording && 
-            !pendingRecording)
+        if (GetState() == kState_WatchingLiveTV)
         {
-            if (QDateTime::currentDateTime() >= curRecording->endts) // change to curRecording->recstartts.addSecs(60) for testing
-                SwitchLiveTVRingBuffer();
+            bool enable_livetv_ui = false;
+            if (pseudoLiveTVRecording &&
+                (QDateTime::currentDateTime() > recordEndTime ||
+                 HasFlags(kFlagFinishRecording)))
+            {
+                SetPseudoLiveTVRecording(NULL);
+                enable_livetv_ui = true;
+            }
+            else if (curRecording &&
+                     !pseudoLiveTVRecording && !pendingRecording)
+            {
+//#define TESTING_RING_BUFFER_SWITCHING
+#ifdef TESTING_RING_BUFFER_SWITCHING
+                if ((QDateTime::currentDateTime() >=
+                     curRecording->recstartts.addSecs(60)))
+#else
+                if ((QDateTime::currentDateTime() >= curRecording->endts))
+#endif
+                {
+                    SwitchLiveTVRingBuffer();
+                    enable_livetv_ui = true;
+                }
+            }
+            if (enable_livetv_ui)
+            {
+                VERBOSE(VB_IMPORTANT, LOC + "Enabling Full LiveTV UI.");
+                QString message = QString("LIVETV_WATCH %1 0").arg(cardid);
+                MythEvent me(message);
+                gContext->dispatch(me);
+            }   
         }
 
         // Check for ExitPlayer flag, and if set change to a non-watching
@@ -2459,21 +2513,80 @@
     return "";
 }
 
-/** \fn TVRec::StopLiveTV()
+/** \fn TVRec::CheckForRecGroupChange(void)
+ *  \brief Check if frontend changed the recording group.
+ *
+ *   This is needed because the frontend may toggle whether something
+ *   should be kept as a recording in the frontend, but this class may
+ *   not find out about it in time unless we check the DB when this
+ *   information is important.
+ */
+void TVRec::CheckForRecGroupChange(void)
+{
+    QMutexLocker lock(&stateChangeLock);
+
+    if (internalState == kState_None)
+        return; // already stopped
+
+    ProgramInfo *pi = NULL;
+    if (curRecording)
+    {
+        pi = ProgramInfo::GetProgramFromRecorded(
+            curRecording->chanid, curRecording->recstartts);
+    }
+
+    if (pi && pi->recgroup != "LiveTV" && !pseudoLiveTVRecording)
+    {
+        // User wants this recording to continue
+        SetPseudoLiveTVRecording(pi);
+        pi = NULL;
+    }
+    else if (pi->recgroup == "LiveTV" && pseudoLiveTVRecording)
+    {
+        // User wants to abandon scheduled recording
+        SetPseudoLiveTVRecording(NULL);
+    }
+
+    if (pi)
+        delete pi;
+}
+
+/** \fn TVRec::StopLiveTV(void)
  *  \brief Tells TVRec to stop a "Live TV" recorder.
  *  \sa EncoderLink::StopLiveTV(), RemoteEncoder::StopLiveTV()
  */
 void TVRec::StopLiveTV(void)
 {
-    if (GetState() != kState_None)
+    QMutexLocker lock(&stateChangeLock);
+    VERBOSE(VB_RECORD, "StopLiveTV(void) curRec: "<<curRecording
+            <<" pseudoRec: "<<pseudoLiveTVRecording);
+
+    if (internalState == kState_None)
+        return; // already stopped
+
+    CheckForRecGroupChange();
+
+    // Figure out next state and if needed recording end time.
+    TVState next_state = kState_None;
+    bool has_cancel = true;
+    if (pseudoLiveTVRecording)
     {
-        QMutexLocker lock(&stateChangeLock);
-        ChangeState(kState_None);
-        // Wait for state change to take effect...
-        WaitForEventThreadSleep();
+        recordEndTime = GetRecordEndTime(pseudoLiveTVRecording);
+        next_state = kState_RecordingOnly;
+        has_cancel = HasFlags(kFlagCancelNextRecording);
+    }
 
-        tvchain = NULL;
-    }
+    // Change to the appropriate state
+    ChangeState(next_state);
+
+    // Wait for state change to take effect...
+    WaitForEventThreadSleep();
+
+    if (has_cancel)
+        SetFlags(kFlagCancelNextRecording);
+
+    // We are done with the tvchain...
+    tvchain = NULL;
 }
 
 /** \fn TVRec::PauseRecorder(void)
@@ -3069,10 +3182,13 @@
     {
         // We need there to be a ringbuffer for these modes
         bool ok;
+        ProgramInfo *tmp = pseudoLiveTVRecording;
+        pseudoLiveTVRecording = NULL;
         if (!ringBuffer)
             ok = CreateLiveTVRingBuffer();
         else
             ok = SwitchLiveTVRingBuffer(true, false);
+        pseudoLiveTVRecording = tmp;
         if (!ok)
         {
             VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create RingBuffer 1");
@@ -3450,6 +3566,27 @@
     // Some recorders unpause on Reset, others do not...
     recorder->Unpause();
 
+    if (pseudoLiveTVRecording)
+    {
+        ProgramInfo *rcinfo1 = pseudoLiveTVRecording; 
+        QString msg1 = QString("Recording: %1 %2 %3 %4")
+            .arg(rcinfo1->title).arg(rcinfo1->chanid)
+            .arg(rcinfo1->recstartts.toString())
+            .arg(rcinfo1->recendts.toString());
+        ProgramInfo *rcinfo2 = tvchain->GetProgramAt(-1);
+        QString msg2 = QString("Recording: %1 %2 %3 %4")
+            .arg(rcinfo2->title).arg(rcinfo2->chanid)
+            .arg(rcinfo2->recstartts.toString())
+            .arg(rcinfo2->recendts.toString());
+        delete rcinfo2;
+        VERBOSE(VB_RECORD, LOC + "Pseudo LiveTV recording starting." +
+                "\n\t\t\t" + msg1 + "\n\t\t\t" + msg2);
+
+        int autoexpiredef = gContext->GetNumSetting("AutoExpireDefault", 0);
+        curRecording->SetAutoExpire(autoexpiredef);
+        curRecording->ApplyRecordRecGroupChange("Default");
+    }
+
     ClearFlags(kFlagNeedToStartRecorder);
 }
 
@@ -3578,10 +3715,14 @@
     }
 
     QString chanids = QString::number(chanid);
-    ProgramInfo *prog = ProgramInfo::GetProgramAtDateTime(chanids, 
-                                                  mythCurrentDateTime(),
-                                                  true);
 
+    ProgramInfo *prog = NULL;
+    if (pseudoLiveTVRecording)
+        prog = new ProgramInfo(*pseudoLiveTVRecording);
+    else
+        prog = ProgramInfo::GetProgramAtDateTime(
+            chanids, mythCurrentDateTime(), true);
+
     if (prog->recstartts == prog->recendts)
     {
         VERBOSE(VB_IMPORTANT, LOC_ERR + "GetProgramRingBufferForLiveTV()"
Index: libs/libmythtv/osd.cpp
===================================================================
--- libs/libmythtv/osd.cpp	(revision 8514)
+++ libs/libmythtv/osd.cpp	(working copy)
@@ -1676,7 +1676,8 @@
 }
 
 void OSD::NewDialogBox(const QString &name, const QString &message, 
-                       QStringList &options, int length)
+                       QStringList &options, int length,
+                       int initial_selection)
 {
     osdlock.lock();
     OSDSet *container = GetSet(name);
@@ -1716,10 +1717,12 @@
     while (text);
 
     int numoptions = options.size();
+    int offset = availoptions - numoptions;
+    initial_selection = max(min(numoptions - 1, initial_selection), 0);
 
     for (int i = 1; i <= numoptions && i <= availoptions; i++)
     {
-        QString name = QString("option%1").arg(availoptions - numoptions + i);
+        QString name = QString("option%1").arg(offset + i);
         text = (OSDTypeText *)container->GetType(name);
         if (!text)
         {
@@ -1740,12 +1743,12 @@
         return;
     }
 
-    opr->SetOffset(availoptions - numoptions);
-    opr->SetPosition(0);
+    opr->SetOffset(offset);
+    opr->SetPosition(initial_selection);
 
     dialogResponseList[name] = 0;
 
-    HighlightDialogSelection(container, availoptions - numoptions);
+    HighlightDialogSelection(container, offset + initial_selection);
 
     if (length > 0)
         container->DisplayFor(length * 1000000);
Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h	(revision 8514)
+++ libs/libmythtv/tv_rec.h	(working copy)
@@ -144,10 +144,7 @@
     void FinishRecording(void)  { SetFlags(kFlagFinishRecording); }
     /// \brief Tells TVRec that the frontend's TV class is ready for messages.
     void FrontendReady(void)    { SetFlags(kFlagFrontendReady); }
-    /** \brief Tells TVRec to cancel the upcoming recording.
-     *  \sa RecordPending(const ProgramInfo*,int),
-     *      TV::AskAllowRecording(const QStringList&,int) */
-    void CancelNextRecording(void) { SetFlags(kFlagCancelNextRecording); }
+    void CancelNextRecording(bool cancel);
     ProgramInfo *GetRecording(void);
 
     /// \brief Returns true if event loop has not been told to shut down
@@ -234,6 +231,7 @@
 
   private:
     void SetRingBuffer(RingBuffer *);
+    void SetPseudoLiveTVRecording(ProgramInfo*);
     void TeardownAll(void);
 
     static bool GetDevices(int cardid,
@@ -290,6 +288,8 @@
 
     void StartedRecording(ProgramInfo*);
     void FinishedRecording(ProgramInfo*);
+    QDateTime GetRecordEndTime(const ProgramInfo*) const;
+    void CheckForRecGroupChange(void);
 
     void SetOption(RecordingProfile &profile, const QString &name);
 
@@ -349,6 +349,9 @@
     ProgramInfo *pendingRecording;
     QDateTime    recordPendingStart;
 
+    // Pseudo LiveTV recording
+    ProgramInfo *pseudoLiveTVRecording;
+
     // LiveTV file chain
     LiveTVChain *tvchain;
 
Index: libs/libmyth/mythcontext.h
===================================================================
--- libs/libmyth/mythcontext.h	(revision 8514)
+++ libs/libmyth/mythcontext.h	(working copy)
@@ -221,7 +221,7 @@
  *   You must also update this value in
  *   mythplugins/mythweb/includes/mythbackend.php
  */
-#define MYTH_PROTO_VERSION "22"
+#define MYTH_PROTO_VERSION "23"
 
 /** \class MythContext
  *  \brief This class contains the runtime context for MythTV.
Index: programs/mythbackend/encoderlink.h
===================================================================
--- programs/mythbackend/encoderlink.h	(revision 8514)
+++ programs/mythbackend/encoderlink.h	(working copy)
@@ -62,7 +62,7 @@
     void StopRecording(void);
     void FinishRecording(void);
     void FrontendReady(void);
-    void CancelNextRecording(void);
+    void CancelNextRecording(bool);
     bool WouldConflict(const ProgramInfo *rec);
 
     bool IsReallyRecording(void);
Index: programs/mythbackend/mainserver.cpp
===================================================================
--- programs/mythbackend/mainserver.cpp	(revision 8514)
+++ programs/mythbackend/mainserver.cpp	(working copy)
@@ -2420,8 +2420,9 @@
     }
     else if (command == "CANCEL_NEXT_RECORDING")
     {
-        VERBOSE(VB_IMPORTANT, "Received: CANCEL_NEXT_RECORDING");
-        enc->CancelNextRecording();
+        QString cancel = slist[2];
+        VERBOSE(VB_IMPORTANT, "Received: CANCEL_NEXT_RECORDING "<<cancel);
+        enc->CancelNextRecording(cancel == "1");
         retlist << "ok";
     }
     else if (command == "SPAWN_LIVETV")
@@ -3596,7 +3597,7 @@
     for (; iter != encoderList->end(); ++iter)
     {
         EncoderLink *elink = iter.data();
-        elink->CancelNextRecording();
+        elink->CancelNextRecording(true);
         ProgramInfo *pinfo = elink->GetRecording();
         pinfo->ToStringList(strlist);
         delete pinfo;
Index: programs/mythbackend/encoderlink.cpp
===================================================================
--- programs/mythbackend/encoderlink.cpp	(revision 8514)
+++ programs/mythbackend/encoderlink.cpp	(working copy)
@@ -203,7 +203,7 @@
  *  \brief Tells TVRec there is a pending recording "rec" in "secsleft" seconds.
  *  \param rec      Recording to make.
  *  \param secsleft Seconds to wait before starting recording.
- *  \sa StartRecording(const ProgramInfo*), CancelNextRecording()
+ *  \sa StartRecording(const ProgramInfo*), CancelNextRecording(bool)
  */
 void EncoderLink::RecordPending(const ProgramInfo *rec, int secsleft)
 {
@@ -568,7 +568,7 @@
         VERBOSE(VB_IMPORTANT, "Should be local only query: FrontendReady");
 }
 
-/** \fn EncoderLink::CancelNextRecording()
+/** \fn EncoderLink::CancelNextRecording(bool)
  *  \brief Tells TVRec to cancel the next recording.
  *         <b>This only works on local recorders.</b>
  *
@@ -577,10 +577,10 @@
  *
  *  \sa RecordPending(const ProgramInfo*,int)
  */
-void EncoderLink::CancelNextRecording(void)
+void EncoderLink::CancelNextRecording(bool cancel)
 {
     if (local)
-        tv->CancelNextRecording();
+        tv->CancelNextRecording(cancel);
     else
         VERBOSE(VB_IMPORTANT, "Should be local only query: CancelNextRecording");
 }
