Ticket #3326: 3326-pendingrecording-v1.patch

File 3326-pendingrecording-v1.patch, 18.3 KB (added by danielk, 13 years ago)

Extends pending recording group with some input group smarts

  • libs/libmythtv/tv_play.cpp

     
    899899    activerecorder->FinishRecording();
    900900}
    901901
    902 void TV::AskAllowRecording(const QStringList &messages, int timeuntil,
     902void TV::AskAllowRecording(const QStringList &msg, int timeuntil,
    903903                           bool hasrec)
    904904{
    905905    if (!StateIsLiveTV(GetState()))
    906906       return;
    907907
    908     QString title = messages[0];
    909     QString chanstr = messages[1];
    910     QString chansign = messages[2];
    911     QString channame = messages[3];
     908    ProgramInfo info;
     909    QStringList::const_iterator it = msg.begin();
     910    info.FromStringList(it, msg.end());
    912911
     912    if (recorder->GetRecorderNumber() != info.cardid)
     913    {
     914        // Check if this is a shared tuner card,
     915        // if so, then either lock mplexid or
     916        // offer menu option to switch to a channel
     917        // on the mplexid.
     918    }
     919
    913920    QString channel = gContext->GetSetting("ChannelFormat", "<num> <sign>");
    914     channel.replace("<num>", chanstr)
    915         .replace("<sign>", chansign)
    916         .replace("<name>", channame);
     921    channel.replace("<num>", info.chanstr)
     922        .replace("<sign>", info.chansign)
     923        .replace("<name>", info.channame);
    917924   
    918925    QString message = QObject::tr(
    919926        "MythTV wants to record \"%1\" on %2 in %3 seconds. Do you want to:")
    920         .arg(title).arg(channel).arg(" %d ");
     927        .arg(info.title).arg(channel).arg(" %d ");
    921928   
    922929    while (!GetOSD())
    923930    {
     
    927934        qApp->lock();
    928935    }
    929936
     937    bool is_this_rec = (recorder->GetRecorderNumber() == info.cardid);
     938
    930939    QStringList options;
    931     options += tr("Record and watch while it records");
     940    if (is_this_rec)
     941        options += tr("Record and watch while it records");
    932942    options += tr("Let it record and go back to the Main Menu");
    933943    options += tr("Don't let it record, I want to watch TV");
    934     int sel = (hasrec) ? 2 : 0;
     944    int sel = (is_this_rec) ? ((hasrec) ? 2 : 0) : 0;
    935945
    936     dialogname = "allowrecordingbox";
     946    dialogname = (is_this_rec) ? "allowrecordingbox" : "allowrecordingbox2";
    937947    GetOSD()->NewDialogBox(dialogname, message, options, timeuntil, sel);
    938948}
    939949
     
    24982508                            break;
    24992509                    }
    25002510                }
    2501                 else if (dialogname == "allowrecordingbox")
     2511                else if (dialogname.left(17) == "allowrecordingbox")
    25022512                {
    25032513                    int result = GetOSD()->GetDialogResponse(dialogname);
    25042514
     2515                    if ((dialogname == "allowrecordingbox2") && (result > 0))
     2516                        result++;
     2517
    25052518                    if (result == 1)
    25062519                        recorder->CancelNextRecording(false);
    25072520                    else if (result == 2)
  • libs/libmythtv/programinfo.h

     
    120120
    121121    ProgramInfo& operator=(const ProgramInfo &other);
    122122    ProgramInfo& clone(const ProgramInfo &other);
    123     bool FromStringList(QStringList &list, int offset);
    124     bool FromStringList(QStringList &list, QStringList::iterator &it);
     123    bool FromStringList(QStringList::const_iterator &it,
     124                        QStringList::const_iterator  end);
     125    bool FromStringList(const QStringList &list, uint offset);
     126
    125127    bool FillInRecordInfo(const vector<ProgramInfo *> &reclist);
    126128   
    127129    // Destructor
  • libs/libmythtv/remoteutil.cpp

     
    186186            return 0;
    187187        }
    188188
    189         QStringList::iterator it = strList.at(1);
     189        QStringList::const_iterator it = strList.at(1);
    190190        for (int i = 0; i < numrecordings; i++)
    191191        {
    192192            ProgramInfo *pginfo = new ProgramInfo();
    193             pginfo->FromStringList(strList, it);
     193            pginfo->FromStringList(it, strList.end());
    194194            reclist->push_back(pginfo);
    195195        }
    196196    }
     
    418418
    419419    QStringList::const_iterator it = strlist.begin();
    420420    bool state = (*it).toInt();
     421    it++;
    421422    busy_input.FromStringList(it, strlist.end());
    422423
    423424    return state;
  • libs/libmythtv/tv_rec.cpp

     
    7878static bool is_dishnet_eit(int cardid);
    7979static QString load_profile(QString,void*,ProgramInfo*,RecordingProfile&);
    8080
     81uint RemoteGetFlags(uint cardid)
     82{
     83    if (gContext->IsBackend())
     84    {
     85        const TVRec *rec = TVRec::GetTVRec(cardid);
     86        if (rec)
     87            return rec->GetFlags();
     88    }
     89
     90    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
     91    strlist << "GET_FLAGS";
     92    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
     93        return 0;
     94
     95    return strlist[0].toInt();
     96}
     97
     98bool RemoteRecordPending(uint cardid, const ProgramInfo *pginfo,
     99                         uint secsleft)
     100{
     101    if (gContext->IsBackend())
     102    {
     103        TVRec *rec = TVRec::GetTVRec(cardid);
     104        if (rec)
     105        {
     106            rec->RecordPending(pginfo, secsleft);
     107            return true;
     108        }
     109    }
     110
     111    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
     112    strlist << "RECORD_PENDING";
     113    strlist << QString::number(secsleft);
     114    pginfo->ToStringList(strlist);
     115
     116    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
     117        return false;
     118
     119    return strlist[0] == "OK";
     120}
     121
     122bool RemoteStopRecording(uint cardid)
     123{
     124    if (gContext->IsBackend())
     125    {
     126        TVRec *rec = TVRec::GetTVRec(cardid);
     127        if (rec)
     128        {
     129            rec->StopRecording();
     130            return true;
     131        }
     132    }
     133
     134    QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(cardid);
     135    strlist << "STOP_RECORDING";
     136
     137    if (!gContext->SendReceiveStringList(strlist) || strlist.empty())
     138        return false;
     139
     140    return strlist[0] == "OK";
     141}
     142
    81143/** \class TVRec
    82144 *  \brief This is the coordinating class of the \ref recorder_subsystem.
    83145 *
     
    362424 *   it. Depending on what that query returns, the recording will be
    363425 *   started or not started.
    364426 *
    365  *  \sa TV::AskAllowRecording(const QStringList&, int)
     427 *  \sa TV::AskAllowRecording(const QStringList&, int, bool)
    366428 *  \param rcinfo   ProgramInfo on pending program.
    367429 *  \param secsleft Seconds left until pending recording begins.
    368430 */
    369431void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft)
    370432{
    371433    QMutexLocker lock(&stateChangeLock);
     434
     435    uint inputid = rcinfo->inputid;
     436    cout<<endl;
     437    VERBOSE(VB_RECORD, LOC +
     438            QString("RecordPending on inputid %1").arg(inputid));
     439
    372440    if (pendingRecording)
    373441        delete pendingRecording;
    374442
    375443    pendingRecording = new ProgramInfo(*rcinfo);
    376444    recordPendingStart = QDateTime::currentDateTime().addSecs(secsleft);
    377445    SetFlags(kFlagAskAllowRecording);
     446
     447    if (rcinfo->cardid != cardid)
     448        return;
     449
     450    // We also need to check our input groups
     451    vector<uint> inputgroupids = CardUtil::GetInputGroups(inputid);
     452
     453    for (uint i = 0; i < inputgroupids.size(); i++)
     454    {
     455        VERBOSE(VB_RECORD, LOC +
     456                QString("  Group ID %1").arg(inputgroupids[i]));
     457    }
     458
     459    vector<uint> cardids;
     460    for (uint i = 0; i < inputgroupids.size(); i++)
     461    {
     462        vector<uint> tmp = CardUtil::GetGroupCardIDs(inputgroupids[i]);
     463        for (uint j = 0; j < tmp.size(); j++)
     464        {
     465            if (tmp[j] == (uint) cardid)
     466                continue;
     467
     468            if (find(cardids.begin(), cardids.end(), tmp[j]) != cardids.end())
     469                continue;
     470
     471            cardids.push_back(tmp[j]);
     472        }
     473    }
     474
     475    for (uint i = 0; i < cardids.size(); i++)
     476        VERBOSE(VB_RECORD, LOC + QString("  Card ID %1").arg(cardids[i]));
     477
     478    pendingRecordingCardIds = cardids;
     479
     480    stateChangeLock.unlock();
     481    for (uint i = 0; i < cardids.size(); i++)
     482        RemoteRecordPending(cardids[i], rcinfo, secsleft);
     483    stateChangeLock.lock();
     484
     485    cout<<endl;
    378486}
    379487
    380488/** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*)
     
    467575    // Flush out events...
    468576    WaitForEventThreadSleep();
    469577
     578    // If the needed input is in a shared input group, and we are
     579    // not canceling the recording anyway, check other recorders
     580    if (pendingRecording && pendingRecordingCardIds.size())
     581    {
     582        cout<<endl;
     583        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin");
     584        vector<uint> &cardids = pendingRecordingCardIds;
     585
     586        // If any LiveTV session decided to cancel recording, don't record
     587        for (uint i = 0; i < cardids.size(); i++)
     588        {
     589            uint flags = RemoteGetFlags(cardids[i]);
     590            if (flags & kFlagCancelNextRecording)
     591            {
     592                SetFlags(kFlagCancelNextRecording);
     593                break;
     594            }
     595        }
     596
     597        // Stop all the remote recordings
     598        uint maxi = HasFlags(kFlagCancelNextRecording) ? cardids.size() : 0;
     599        bool ok = true;
     600        for (uint i = 0; (i < maxi) && ok; i++)
     601        {
     602            VERBOSE(VB_RECORD, LOC + QString("Attempting to stop card %1")
     603                    .arg(cardids[i]));
     604            ok &= RemoteStopRecording(cardids[i]);
     605        }
     606
     607        cardids.clear();
     608
     609        // If we failed to stop the remote recordings, don't record
     610        if (!ok)
     611            SetFlags(kFlagCancelNextRecording);
     612        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - done\n");
     613    }
     614
    470615    // If in post-roll, end recording
    471616    if (GetState() == kState_RecordingOnly &&
    472617        !HasFlags(kFlagCancelNextRecording))
     
    476621        stateChangeLock.lock();
    477622    }
    478623
    479     if (internalState == kState_None)
     624    if (!HasFlags(kFlagCancelNextRecording) &&
     625        (GetState() == kState_None))
    480626    {
    481627        if (tvchain)
    482628        {
     
    12151361                    .arg(cardid).arg(timeuntil)
    12161362                    .arg(pseudoLiveTVRecording ? 1 : 0);
    12171363                VERBOSE(VB_IMPORTANT, LOC + query);
    1218                 QStringList messages;
    1219                 messages << pendingRecording->title
    1220                          << pendingRecording->chanstr
    1221                          << pendingRecording->chansign
    1222                          << pendingRecording->channame;
    1223                 MythEvent me(query, messages);
     1364
     1365                QStringList msg;
     1366                pendingRecording->ToStringList(msg);
     1367                MythEvent me(query, msg);
    12241368                gContext->dispatch(me);
    12251369            }
    12261370        }
  • libs/libmythtv/programinfo.cpp

     
    275275/** \fn ProgramInfo::ToStringList(QStringList&) const
    276276 *  \brief Serializes ProgramInfo into a QStringList which can be passed
    277277 *         over a socket.
    278  *  \sa FromStringList(QStringList&,int),
    279  *      FromStringList(QStringList&,QStringList::iterator&)
     278 *  \sa FromStringList(QStringList::const_iterator&,
     279                       QStringList::const_iterator)
    280280 */
    281281void ProgramInfo::ToStringList(QStringList &list) const
    282282{
     
    327327    STR_TO_LIST((storagegroup != "") ? storagegroup : "Default")
    328328}
    329329
    330 /** \fn ProgramInfo::FromStringList(QStringList&,int)
     330/** \fn ProgramInfo::FromStringList(const QStringList&,uint)
    331331 *  \brief Uses a QStringList to initialize this ProgramInfo instance.
     332 *
     333 *  This is a convenience method which calls FromStringList(
     334    QStringList::const_iterator&,QStringList::const_iterator)
     335 *  with an iterator created using list.at(offset).
     336 *
    332337 *  \param list   QStringList containing serialized ProgramInfo.
    333338 *  \param offset First field in list to treat as beginning of
    334339 *                serialized ProgramInfo.
    335340 *  \return true if it succeeds, false if it fails.
    336  *  \sa ToStringList(QStringList&),
    337  *      FromStringList(QStringList&,QStringList::iterator&)
     341 *  \sa FromStringList(QStringList::const_iterator&,
     342                       QStringList::const_iterator)
     343 *      ToStringList(QStringList&) const
    338344 */
    339 bool ProgramInfo::FromStringList(QStringList &list, int offset)
     345bool ProgramInfo::FromStringList(const QStringList &list, uint offset)
    340346{
    341     QStringList::iterator it = list.at(offset);
    342     return FromStringList(list, it);
     347    QStringList::const_iterator it = list.at(offset);
     348    return FromStringList(it, list.end());
    343349}
    344350
    345351#define NEXT_STR()             if (it == listend)     \
     
    365371
    366372#define FLOAT_FROM_LIST(x)     NEXT_STR() (x) = atof(ts.ascii());
    367373
    368 /** \fn ProgramInfo::FromStringList(QStringList&,QStringList::iterator&)
     374/** \fn ProgramInfo::FromStringList(QStringList::const_iterator&,
     375                                    QStringList::const_iterator)
    369376 *  \brief Uses a QStringList to initialize this ProgramInfo instance.
    370  *  \param list   QStringList containing serialized ProgramInfo.
    371  *  \param it     Iterator pointing to first field in list to treat as
     377 *  \param beg    Iterator pointing to first item in list to treat as
    372378 *                beginning of serialized ProgramInfo.
     379 *  \param end    Iterator that will stop parsing of the ProgramInfo
    373380 *  \return true if it succeeds, false if it fails.
    374  *  \sa ToStringList(QStringList&), FromStringList(QStringList&,int)
     381 *  \sa FromStringList(const QStringList&,uint)
     382 *      ToStringList(QStringList&) const
    375383 */
    376 bool ProgramInfo::FromStringList(QStringList &list, QStringList::iterator &it)
     384
     385bool ProgramInfo::FromStringList(QStringList::const_iterator &it,
     386                                 QStringList::const_iterator  listend)
    377387{
    378     const char* listerror = LOC + "FromStringList, not enough items in list.\n";
    379     QStringList::iterator listend = list.end();
     388    QString listerror = LOC + "FromStringList, not enough items in list.";
    380389    QString ts;
    381390    int ti;
    382391
     
    44764485    hasConflicts = slist[0].toInt();
    44774486
    44784487    bool result = true;
    4479     QStringList::Iterator sit = slist.at(2);
     4488    QStringList::const_iterator sit = slist.at(2);
    44804489
    44814490    while (result && sit != slist.end())
    44824491    {
    44834492        ProgramInfo *p = new ProgramInfo();
    4484         result = p->FromStringList(slist, sit);
     4493        result = p->FromStringList(sit, slist.end());
    44854494        if (result)
    44864495            append(p);
    44874496        else
  • libs/libmythtv/tv_rec.h

     
    223223
    224224    void SetNextLiveTVDir(QString dir);
    225225
     226    uint GetFlags(void) const { return stateFlags; }
     227
    226228    static TVRec *GetTVRec(uint cardid);
    227229
    228230  public slots:
     
    364366    // Pending recording info
    365367    ProgramInfo *pendingRecording;
    366368    QDateTime    recordPendingStart;
     369    vector<uint> pendingRecordingCardIds;
    367370
    368371    // Pseudo LiveTV recording
    369372    ProgramInfo *pseudoLiveTVRecording;
     
    378381    RingBuffer  *ringBuffer;
    379382    QString      rbFileExt;
    380383
    381   public:
    382384    static QMutex            cardsLock;
    383385    static QMap<uint,TVRec*> cards;
    384386
  • programs/mythbackend/encoderlink.h

     
    5454    bool IsBusyRecording(void);
    5555
    5656    TVState GetState();
     57    uint GetFlags(void) const;
    5758    bool IsRecording(const ProgramInfo *rec); // scheduler call only.
    5859
    5960    bool MatchesRecording(const ProgramInfo *rec);
  • programs/mythbackend/mainserver.cpp

     
    937937        {
    938938            ProgramInfo pinfo;
    939939            ProgramList slavelist;
    940             QStringList::Iterator sit = slist.at(1);
     940            QStringList::const_iterator sit = slist.at(1);
    941941            while (sit != slist.end())
    942942            {
    943                 if (!pinfo.FromStringList(slist, sit))
     943                if (!pinfo.FromStringList(sit, slist.end()))
    944944                    break;
    945945                slavelist.append(new ProgramInfo(pinfo));
    946946            }
     
    30843084    {
    30853085        retlist << QString::number((int)enc->GetState());
    30863086    }
    3087     if (command == "IS_BUSY")
     3087    else if (command == "GET_FLAGS")
    30883088    {
     3089        retlist << QString::number(enc->GetFlags());
     3090    }
     3091    else if (command == "IS_BUSY")
     3092    {
    30893093        TunedInputInfo busy_input;
    30903094        retlist << QString::number((int)enc->IsBusy(&busy_input));
    30913095        busy_input.ToStringList(retlist);
     
    31193123        retlist << "OK";
    31203124        delete pginfo;
    31213125    }
     3126    else if (command == "STOP_RECORDING")
     3127    {
     3128        enc->StopRecording();
     3129        retlist << "OK";
     3130    }
    31223131    else if (command == "GET_MAX_BITRATE")
    31233132    {
    31243133        long long value = enc->GetMaxBitrate();
  • programs/mythbackend/encoderlink.cpp

     
    1515#include "previewgenerator.h"
    1616#include "storagegroup.h"
    1717
     18#define LOC QString("EncoderLink(%1): ").arg(m_capturecardnum)
     19#define LOC_ERR QString("EncoderLink(%1) Error: ").arg(m_capturecardnum)
     20
    1821/**
    1922 * \class EncoderLink
    2023 * \brief Provides an interface to both local and remote TVRec's for the mythbackend.
     
    143146    return retval;
    144147}
    145148
     149/** \fn EncoderLink::GetFlags(void) const
     150 *  \brief Returns the flag state of the recorder.
     151 *  \sa TVRec::GetFlags(void) const, \ref recorder_subsystem
     152 */
     153uint EncoderLink::GetFlags(void) const
     154{
     155    uint retval = 0;
     156
     157    if (!IsConnected())
     158        return retval;
     159
     160    if (local)
     161        retval = tv->GetFlags();
     162    else if (sock)
     163        retval = sock->GetEncoderState(m_capturecardnum);
     164    else
     165        VERBOSE(VB_IMPORTANT, LOC_ERR + "GetFlags failed");
     166
     167    return retval;
     168}
     169
    146170/** \fn EncoderLink::IsRecording(const ProgramInfo *rec)
    147171 *  \brief Returns true if rec is scheduled for recording.
    148172 *  \param rec Recording to check.