Ticket #1772: ajm_multiple_recorders.patch

File ajm_multiple_recorders.patch, 51.6 KB (added by Aaron McCarthy <mccarthy.aaron@…>, 14 years ago)
  • libs/libmythtv/tv_rec.h

    old new  
    169169    void RecordPending(const ProgramInfo *rcinfo, int secsleft);
    170170    RecStatusType StartRecording(const ProgramInfo *rcinfo);
    171171
    172     void StopRecording(void);
     172    void StopRecording(ProgramInfo *rec);
    173173    /// \brief Tells TVRec to finish the current recording as soon as possible.
    174174    void FinishRecording(void)  { SetFlags(kFlagFinishRecording); }
    175175    /// \brief Tells TVRec that the frontend's TV class is ready for messages.
    176176    void FrontendReady(void)    { SetFlags(kFlagFrontendReady); }
    177177    void CancelNextRecording(bool cancel);
    178     ProgramInfo *GetRecording(void);
     178    ProgramList GetRecordings(void);
    179179
    180180    /// \brief Returns true if event loop has not been told to shut down
    181181    bool IsRunning(void)  const { return HasFlags(kFlagRunMainLoop); }
     
    346346
    347347    void SetOption(RecordingProfile &profile, const QString &name);
    348348
     349    void DoneAddingRecording();
     350
    349351    // Various components TVRec coordinates
    350352    RecorderMuxBase  *recorderMux;
    351     RecorderBase     *recorder;
     353    QMap<ProgramInfo *, RecorderBase *>  recorders;
    352354    ChannelBase      *channel;
    353355    SignalMonitor    *signalMonitor;
    354356    EITScanner       *scanner;
     
    392394    QWaitCondition triggerEventLoop;
    393395    QWaitCondition triggerEventSleep;
    394396
     397    // Current recording info SPLIT
     398    ProgramList   curRecordings;
     399    ProgramInfo  *newRecording;
     400    RecorderBase *newRecorder;
     401    QMutex        newRecordingLock;
     402
    395403    // Current recording info
    396404    ProgramInfo *curRecording;
    397405    QDateTime    recordEndTime;
     
    408416    // LiveTV file chain
    409417    LiveTVChain *tvchain;
    410418
     419    // RingBuffer info SPLIT
     420    RingBuffer *newRingBuffer;
     421    QMap<ProgramInfo *, RingBuffer *> ringBuffers;
     422
    411423    // RingBuffer info
    412424    RingBuffer  *ringBuffer;
    413425    QString      rbFilePrefix;
  • libs/libmythtv/tv_rec.cpp

    old new  
    9292static bool is_dishnet_eit(int cardid);
    9393static QString load_profile(QString,void*,ProgramInfo*,RecordingProfile&);
    9494
     95static int comp_recend(ProgramInfo *a, ProgramInfo *b)
     96{
     97    if (a->recendts != b->recendts)
     98    {
     99        if (a->recendts > b->recendts)
     100            return 1;
     101        else
     102            return -1;
     103    }
     104    if (a->recstartts != b->recstartts)
     105    {
     106        if (a->recstartts > b->recstartts)
     107            return 1;
     108        else
     109            return -1;
     110    }
     111    if (a->chansign != b->chansign)
     112    {
     113        if (a->chansign < b->chansign)
     114            return 1;
     115        else
     116            return -1;
     117    }
     118    return 0;
     119}
     120
    95121/** \class TVRec
    96122 *  \brief This is the coordinating class of the \ref recorder_subsystem.
    97123 *
     
    118144 */
    119145TVRec::TVRec(int capturecardnum)
    120146       // Various components TVRec coordinates
    121     : recorderMux(NULL), recorder(NULL), channel(NULL), signalMonitor(NULL),
     147    : recorderMux(NULL), channel(NULL), signalMonitor(NULL),
    122148      scanner(NULL), dvbsiparser(NULL),
    123149      // Configuration variables from database
    124150      transcodeFirst(false), earlyCommFlag(false), runJobOnHostOnly(false),
     
    131157      internalState(kState_None), desiredNextState(kState_None),
    132158      changeState(false), pauseNotify(true),
    133159      stateFlags(0), lastTuningRequest(0),
     160      // Current recording info SPLIT
     161      curRecordings(false), newRecording(NULL), newRecorder(NULL),
    134162      // Current recording info
    135163      curRecording(NULL), autoRunJobs(JOB_NONE),
    136164      // Pending recording info
     
    139167      pseudoLiveTVRecording(NULL),
    140168      // tvchain
    141169      tvchain(NULL),
     170      // RingBuffer info SPLIT
     171      newRingBuffer(NULL),
    142172      // RingBuffer info
    143173      ringBuffer(NULL), rbFilePrefix(""), rbFileExt("mpg")
    144174{
     
    328358    return internalState;
    329359}
    330360
    331 /** \fn TVRec::GetRecording(void)
    332  *  \brief Allocates and returns a ProgramInfo for the current recording.
     361/** \fn TVRec::GetRecordings(void)
     362 *  \brief Allocates and returns a ProgramList for the current recordings.
    333363 *
    334  *  Note: The user of this function must free the %ProgramInfo this returns.
    335  *  \return %ProgramInfo for the current recording, if it exists, blank
    336  *          %ProgramInfo otherwise.
     364 *  Note: The user of this function must free the %ProgramInfo objects
     365 *  this returns.
     366 *  \return %ProgramList for the current recordings, an empty list is
     367 *          returned if there are no current recordings.
    337368 */
    338 ProgramInfo *TVRec::GetRecording(void)
     369ProgramList TVRec::GetRecordings(void)
    339370{
    340371    QMutexLocker lock(&stateChangeLock);
    341372
    342     ProgramInfo *tmppginfo = NULL;
     373    ProgramList retlist(false);
     374
     375    if (changeState)
     376        return retlist;
    343377
    344     if (curRecording && !changeState)
     378    for (ProgramInfo *rec = curRecordings.first();
     379         rec; rec = curRecordings.next())
    345380    {
    346         tmppginfo = new ProgramInfo(*curRecording);
     381        ProgramInfo *tmppginfo = new ProgramInfo(*rec);
    347382        tmppginfo->recstatus = rsRecording;
     383        tmppginfo->cardid = cardid;
     384        retlist.append(tmppginfo);
    348385    }
    349     else
    350         tmppginfo = new ProgramInfo();
    351     tmppginfo->cardid = cardid;
    352386
    353     return tmppginfo;
     387    return retlist;
    354388}
    355389
    356390/** \fn TVRec::RecordPending(const ProgramInfo*, int)
     
    417451 *  \return +1 if the recording started successfully,
    418452 *          -1 if TVRec is busy doing something else, 0 otherwise.
    419453 *  \sa EncoderLink::StartRecording(const ProgramInfo*)
    420  *      RecordPending(const ProgramInfo*, int), StopRecording()
     454 *      RecordPending(const ProgramInfo*, int), StopRecording(ProgramInfo *rec)
    421455 */
    422456RecStatusType TVRec::StartRecording(const ProgramInfo *rcinfo)
    423457{
     
    433467
    434468    // We need to do this check early so we don't cancel an overrecord
    435469    // that we're trying to extend.
    436     if (internalState != kState_WatchingLiveTV &&
    437         curRecording &&
     470    if (internalState != kState_WatchingLiveTV)
     471    {
     472        // change this to rec later
     473        for (ProgramInfo *curRecording = curRecordings.first(); curRecording;
     474             curRecording = curRecordings.next())
     475        {
     476            if (curRecording &&
    438477        curRecording->title == rcinfo->title &&
    439478        curRecording->chanid == rcinfo->chanid &&
    440479        curRecording->startts == rcinfo->startts)
     
    447486        MythEvent me("RECORDING_LIST_CHANGE");
    448487        gContext->dispatch(me);
    449488
    450         recordEndTime = curRecording->recendts.addSecs(post_roll_seconds);
     489                // Resort the list of current recordings so that the recording
     490                // that will end first is at the front of the list
     491                curRecordings.Sort(comp_recend);
     492                recordEndTime = curRecordings.getFirst()->recendts.addSecs(post_roll_seconds);
    451493
    452494        msg = QString("updating recording: %1 %2 %3 %4")
    453495            .arg(curRecording->title).arg(curRecording->chanid)
     
    459501
    460502        retval = rsRecording;
    461503        return retval;
     504            }
     505        }
    462506    }
    463507
    464508    if (pendingRecording)
     
    472516    // Flush out events...
    473517    WaitForEventThreadSleep();
    474518
     519    // SPLIT how does this test if recording is in post-roll?
    475520    // If in post-roll, end recording
     521#if 0
    476522    if (GetState() == kState_RecordingOnly &&
    477523        !HasFlags(kFlagCancelNextRecording))
    478524    {
     
    480526        StopRecording();
    481527        stateChangeLock.lock();
    482528    }
     529#endif
    483530
    484531    if (internalState == kState_None)
    485532    {
     
    491538            tvchain = NULL;
    492539        }
    493540
    494         recordEndTime = GetRecordEndTime(rcinfo);
    495 
    496541        // Tell event loop to begin recording.
    497         curRecording = new ProgramInfo(*rcinfo);
    498         curRecording->MarkAsInUse(true, "recorder");
    499         StartedRecording(curRecording);
     542        newRecordingLock.lock();
     543        newRecording = new ProgramInfo(*rcinfo);
     544        newRecording->MarkAsInUse(true, "recorder");
     545        StartedRecording(newRecording);
    500546
    501547        // Make sure scheduler is allowed to end this recording
    502548        ClearFlags(kFlagCancelNextRecording);
     
    522568
    523569        retval = rsRecording;
    524570    }
     571    else if (!HasFlags(kFlagCancelNextRecording) && true /* OnSameMux (this should be true if the scheduler is working right)*/)
     572    {
     573        // Haven't integrated with LiveTV yet
     574        newRecordingLock.lock();
     575        newRecording = new ProgramInfo(*rcinfo);
     576        newRecording->MarkAsInUse(true, "recorder");
     577        StartedRecording(newRecording);
     578
     579        retval = rsRecording;
     580    }
    525581    else if (!HasFlags(kFlagCancelNextRecording))
    526582    {
    527583        msg = QString("Wanted to record: %1 %2 %3 %4\n"
     
    530586              .arg(rcinfo->recstartts.toString())
    531587              .arg(rcinfo->recendts.toString())
    532588              .arg(StateToString(internalState));
    533         if (curRecording && internalState == kState_RecordingOnly)
     589        if (!curRecordings.isEmpty() && internalState == kState_RecordingOnly)
     590        {
     591            // Change this to rec later
     592            for (ProgramInfo *curRecording = curRecordings.first();
     593                 curRecording; curRecording = curRecordings.next())
     594            {
    534595            msg += QString("\n\t\t\tCurrently recording: %1 %2 %3 %4")
    535596                .arg(curRecording->title).arg(curRecording->chanid)
    536597                .arg(curRecording->recstartts.toString())
    537598                .arg(curRecording->recendts.toString());
     599            }
     600        }
    538601        VERBOSE(VB_IMPORTANT, LOC + msg);
    539602
    540603        retval = rsTunerBusy;
     
    545608    return retval;
    546609}
    547610
    548 /** \fn TVRec::StopRecording(void)
     611/** \fn TVRec::StopRecording(ProgramInfo *rec)
    549612 *  \brief Changes from kState_RecordingOnly to kState_None.
    550613 *  \sa StartRecording(const ProgramInfo *rec), FinishRecording()
    551614 */
    552 void TVRec::StopRecording(void)
     615void TVRec::StopRecording(ProgramInfo *rec)
    553616{
    554     if (StateIsRecording(GetState()))
     617    if (curRecordings.contains(rec))
     618    {
     619        recorders[rec]->StopRecording();
     620        FinishedRecording(rec);
     621        curRecordings.remove(rec);
     622
     623        if (!curRecordings.isEmpty())
     624            recordEndTime = GetRecordEndTime(curRecordings.getFirst());
     625    }
     626
     627    if (curRecordings.isEmpty() && StateIsRecording(GetState()))
    555628    {
    556629        QMutexLocker lock(&stateChangeLock);
    557630        ChangeState(RemoveRecording(GetState()));
     
    748821    else if (TRANSITION(kState_None, kState_RecordingOnly))
    749822    {
    750823        SetPseudoLiveTVRecording(NULL);
    751         tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording));
     824        tuningRequests.enqueue(TuningRequest(kFlagRecording, newRecording));
    752825        SET_NEXT();
    753826    }
    754827    else if (TRANSITION(kState_RecordingOnly, kState_None))
     
    803876void TVRec::SetOption(RecordingProfile &profile, const QString &name)
    804877{
    805878    int value = profile.byName(name)->getValue().toInt();
    806     recorder->SetOption(name, value);
     879    newRecorder->SetOption(name, value);
    807880}
    808881
    809882/** \fn TVRec::SetupRecorderMux(RecordingProfile&)
     
    9411014 */
    9421015bool TVRec::SetupNewRecorder(RecordingProfile &profile)
    9431016{
    944     recorder = recorderMux->CreateNewRecorder(this);
     1017    newRecorder = recorderMux->CreateNewRecorder(this);
    9451018    if (genOpt.cardtype == "MPEG")
    9461019    {
    9471020#ifdef USING_IVTV
     
    9521025    {
    9531026#ifdef USING_V4L
    9541027        VERBOSE(VB_RECORD, LOC + QString("Creating new HDTVRecorder"));
    955         ringBuffer->SetWriteBufferSize(4*1024*1024);
    956         recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
     1028        newRingBuffer->SetWriteBufferSize(4*1024*1024);
     1029        newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
    9571030#endif // USING_V4L
    9581031    }
    9591032    else if (genOpt.cardtype == "FIREWIRE")
     
    9631036        VERBOSE(VB_RECORD, LOC + QString("Creating new DarwinFirewireRecorder"));
    9641037# else
    9651038        VERBOSE(VB_RECORD, LOC + QString("Creating new FirewireRecorder"));
    966         recorder->SetOption("port",       fwOpt.port);
    967         recorder->SetOption("node",       fwOpt.node);
    968         recorder->SetOption("speed",      fwOpt.speed);
    969         recorder->SetOption("model",      fwOpt.model);
    970         recorder->SetOption("connection", fwOpt.connection);
     1039        newRecorder->SetOption("port",       fwOpt.port);
     1040        newRecorder->SetOption("node",       fwOpt.node);
     1041        newRecorder->SetOption("speed",      fwOpt.speed);
     1042        newRecorder->SetOption("model",      fwOpt.model);
     1043        newRecorder->SetOption("connection", fwOpt.connection);
    9711044# endif // !CONFIG_DARWIN
    9721045#endif // USING_FIREWIRE
    9731046    }
     
    9751048    {
    9761049#ifdef USING_DBOX2
    9771050        VERBOSE(VB_RECORD, LOC + QString("Creating new DBox2Recorder"));
    978         recorder->SetOption("port",     dboxOpt.port);
    979         recorder->SetOption("host",     dboxOpt.host);
    980         recorder->SetOption("httpport", dboxOpt.httpport);
     1051        newRecorder->SetOption("port",     dboxOpt.port);
     1052        newRecorder->SetOption("host",     dboxOpt.host);
     1053        newRecorder->SetOption("httpport", dboxOpt.httpport);
    9811054#endif // USING_DBOX2
    9821055    }
    9831056    else if (genOpt.cardtype == "HDHOMERUN")
    9841057    {
    9851058#ifdef USING_HDHOMERUN
    9861059        VERBOSE(VB_RECORD, LOC + QString("Creating new HDHRRecorder"));
    987         ringBuffer->SetWriteBufferSize(4*1024*1024);
    988         recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
     1060        newRingBuffer->SetWriteBufferSize(4*1024*1024);
     1061        newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
    9891062#endif // USING_HDHOMERUN
    9901063    }
    9911064    else if (genOpt.cardtype == "DVB")
    9921065    {
    9931066#ifdef USING_DVB
    9941067        VERBOSE(VB_RECORD, LOC + QString("Creating new DVBRecorder"));
    995         ringBuffer->SetWriteBufferSize(4*1024*1024);
    996         recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
    997         recorder->SetOption("dvb_on_demand",     dvbOpt.dvb_on_demand);
     1068        newRingBuffer->SetWriteBufferSize(4*1024*1024);
     1069        newRecorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
     1070        newRecorder->SetOption("dvb_on_demand",     dvbOpt.dvb_on_demand);
    9981071#endif // USING_DVB
    9991072    }
    10001073    else
     
    10021075#ifdef USING_V4L
    10031076        // V4L/MJPEG/GO7007 from here on
    10041077        VERBOSE(VB_RECORD, LOC + QString("Creating new NuppelVideoRecorder"));
    1005         recorder->SetOption("skipbtaudio", genOpt.skip_btaudio);
     1078        newRecorder->SetOption("skipbtaudio", genOpt.skip_btaudio);
    10061079#endif // USING_V4L
    10071080    }
    10081081
    1009     if (recorder)
     1082    if (newRecorder)
    10101083    {
    1011         recorder->SetOptionsFromProfile(
     1084        newRecorder->SetOptionsFromProfile(
    10121085            &profile, genOpt.videodev, genOpt.audiodev, genOpt.vbidev);
    1013         recorder->SetRingBuffer(ringBuffer);
    1014         recorder->Initialize();
     1086        newRecorder->SetRingBuffer(newRingBuffer);
     1087        newRecorder->Initialize();
    10151088
    10161089        return true;
    10171090    }
     
    10501123
    10511124    VERBOSE(VB_RECORD, LOC + "TeardownRecorder - Start");
    10521125
     1126    // SPLIT This should shutdown each recorder
     1127    if (!recorders.isEmpty())
     1128    {
     1129        VERBOSE(VB_RECORD, LOC + "There are still recorders attached to mux");
     1130    }
     1131
    10531132    if (recorderMux && HasFlags(kFlagRecorderRunning))
    10541133    {
    10551134        // This is a bad way to calculate this, the framerate
     
    10811160
    10821161        delete recorderMux;
    10831162        recorderMux = NULL;
    1084         delete recorder;
    1085         recorder = NULL;
    10861163    }
    10871164
     1165    // SPLIT this should be deleted
    10881166    if (ringBuffer)
    10891167        ringBuffer->StopReads();
    10901168
     1169    // SPLIT this should be deleted, or atleast move to where each recording
     1170    // is stoped
    10911171    if (curRecording)
    10921172    {
    10931173        if (!killFile)
     
    11531233DVBRecorder *TVRec::GetDVBRecorder(void)
    11541234{
    11551235#ifdef USING_DVB
    1156     return dynamic_cast<DVBRecorder*>(recorder);
     1236    return dynamic_cast<DVBRecorder*>(newRecorder);
    11571237#else // if !USING_DVB
    11581238    return NULL;
    11591239#endif // !USING_DVB
     
    11621242HDTVRecorder *TVRec::GetHDTVRecorder(void)
    11631243{
    11641244#ifdef USING_V4L
    1165     return dynamic_cast<HDTVRecorder*>(recorder);
     1245    return dynamic_cast<HDTVRecorder*>(newRecorder);
    11661246#else // if !USING_V4L
    11671247    return NULL;
    11681248#endif // USING_V4L
     
    11711251HDHRRecorder *TVRec::GetHDHRRecorder(void)
    11721252{
    11731253#ifdef USING_HDHOMERUN
    1174     return dynamic_cast<HDHRRecorder*>(recorder);
     1254    return dynamic_cast<HDHRRecorder*>(newRecorder);
    11751255#else // if !USING_HDHOMERUN
    11761256    return NULL;
    11771257#endif // !USING_HDHOMERUN
     
    13871467
    13881468    while (HasFlags(kFlagRunMainLoop))
    13891469    {
     1470        if (newRecording)
     1471            VERBOSE(VB_RECORD, LOC + QString("Noticed newRecording(%1)").arg(newRecording->title));
     1472
    13901473        // If there is a state change queued up, do it...
    13911474        if (changeState)
    13921475        {
     1476            VERBOSE(VB_RECORD, LOC + "SPLIT: changeState");
    13931477            HandleStateChange();
    13941478            ClearFlags(kFlagFrontendReady | kFlagCancelNextRecording);
    13951479            SetFlags(kFlagAskAllowRecording);
     
    14071491        // Handle any tuning events..
    14081492        HandleTuning();
    14091493
     1494        // SPLIT
     1495        // Additional new recordings on the same mux are added here
     1496        // Setup the recorder
     1497        if (newRecording)
     1498        {
     1499            VERBOSE(VB_RECORD, LOC + "Adding additional recorders");
     1500
     1501            RecordingProfile profile;
     1502            QString profileName = load_profile(genOpt.cardtype, NULL, newRecording, profile);
     1503
     1504            SetRingBuffer(new RingBuffer(newRecording->GetFileName(), true));
     1505
     1506            if (!SetupNewRecorder(profile))
     1507                VERBOSE(VB_RECORD, LOC_ERR + "Failed to add an additional recorder!");
     1508
     1509            newRecorder->SetRecording(newRecording);
     1510
     1511            DoneAddingRecording();
     1512        }
     1513        // End add additional new recordings on the same mux
     1514        // new recordings should be added to the list by now
     1515
    14101516        // If we have a pending recording and AskAllowRecording is set
    14111517        // and the frontend is ready send an ASK_RECORDING query to frontend.
    14121518        if (pendingRecording && HasFlags(kFlagAskAllowRecording))
    14131519        {
     1520            VERBOSE(VB_RECORD, LOC + "SPLIT: Ask Allow Recording");
    14141521            ClearFlags(kFlagAskAllowRecording);
    14151522
    14161523            if (GetState() == kState_WatchingLiveTV)
     
    14441551            (QDateTime::currentDateTime() > recordEndTime ||
    14451552             HasFlags(kFlagFinishRecording)))
    14461553        {
    1447             ChangeState(kState_None);
     1554            VERBOSE(VB_RECORD, LOC + "SPLIT: Finishing Previous Recording");
     1555            StopRecording(curRecordings.first());
     1556            if (curRecordings.isEmpty())
     1557                ChangeState(kState_None);
    14481558            ClearFlags(kFlagFinishRecording);
    14491559        }
    14501560
    1451         if (curRecording)
    1452             curRecording->UpdateInUseMark();
     1561        for (ProgramInfo *rec = curRecordings.first();
     1562             rec; rec = curRecordings.next())
     1563        {
     1564            rec->UpdateInUseMark();
     1565        }
    14531566
    14541567        // Check for the end of the current program..
    14551568        if (GetState() == kState_WatchingLiveTV)
    14561569        {
     1570            VERBOSE(VB_RECORD, LOC + "SPLIT: Watching LiveTV");
    14571571#define LIVETV_END (now >= curRecording->endts)
    14581572// use the following instead to test ringbuffer switching
    14591573//static QDateTime last = QDateTime::currentDateTime();
     
    14971611        // state (either kState_RecordingOnly or kState_None).
    14981612        if (HasFlags(kFlagExitPlayer))
    14991613        {
     1614            VERBOSE(VB_RECORD, LOC + "SPLIT: Exit Player");
    15001615            if (internalState == kState_WatchingLiveTV)
    15011616                ChangeState(kState_None);
    15021617            else if (StateIsPlaying(internalState))
     
    15381653        }
    15391654    }
    15401655 
     1656    VERBOSE(VB_RECORD, LOC + "SPLIT: RunTV exited while loop");
     1657
    15411658    if (GetState() != kState_None)
    15421659    {
    15431660        ChangeState(kState_None);
     
    23532470
    23542471        videoFilters = query.value(0).toString();
    23552472
    2356         if (recorder != NULL)
     2473        if (newRecorder)
    23572474        {
    2358             recorder->SetVideoFilters(videoFilters);
     2475            newRecorder->SetVideoFilters(videoFilters);
    23592476        }
    23602477
    23612478        return true;
     
    27042821 *  \sa EncoderLink::GetFramesWritten(), RemoteEncoder::GetFramesWritten()
    27052822 *  \return Number of frames if query succeeds, -1 otherwise.
    27062823 */
     2824// SPLIT this should take in a ProgramInfo *
    27072825long long TVRec::GetFramesWritten(void)
    27082826{
    27092827    QMutexLocker lock(&stateChangeLock);
    27102828
    2711     if (recorder)
    2712         return recorder->GetFramesWritten();
     2829    if (newRecorder)
     2830        return newRecorder->GetFramesWritten();
    27132831    return -1;
    27142832}
    27152833
     
    27352853 *      RemoteEncoder::GetKeyframePosition(long long)
    27362854 *  \return Byte position of keyframe if query succeeds, -1 otherwise.
    27372855 */
     2856// SPLIT this thould take in a ProgramInfo *
    27382857long long TVRec::GetKeyframePosition(long long desired)
    27392858{
    27402859    QMutexLocker lock(&stateChangeLock);
    27412860
    2742     if (recorder)
    2743         return recorder->GetKeyframePosition(desired);
     2861    if (newRecorder)
     2862        return newRecorder->GetKeyframePosition(desired);
    27442863    return -1;
    27452864}
    27462865
     
    34953614{
    34963615    QMutexLocker lock(&stateChangeLock);
    34973616
    3498     RingBuffer *rb_old = ringBuffer;
    3499     ringBuffer = rb;
     3617    RingBuffer *rb_old = newRingBuffer;
     3618    newRingBuffer = rb;
    35003619
    35013620    if (rb_old && (rb_old != rb))
    35023621    {
     
    35623681
    35633682    if (HasFlags(kFlagWaitingForRecPause))
    35643683    {
     3684        VERBOSE(VB_RECORD, LOC + QString("RecorderMux = %1").arg((unsigned int)recorderMux));
    35653685        if (!recorderMux->IsPaused())
    35663686            return;
    35673687
    35683688        ClearFlags(kFlagWaitingForRecPause);
    35693689#ifdef USING_DVB
    3570         if (GetDVBRecorder())
     3690        if (GetDVBRecorderMux() && GetDVBRecorder())
    35713691        {
    35723692            // We currently need to close the file descriptor for
    35733693            // DVB signal monitoring to work with some drivers
     
    38463966
    38473967    if (use_dr)
    38483968    {
     3969        VERBOSE(VB_RECORD, LOC + "SPLIT: Using Dummy Recorder");
    38493970        // We need there to be a ringbuffer for these modes
    38503971        bool ok;
    38513972        ProgramInfo *tmp = pseudoLiveTVRecording;
     
    40644185
    40654186    if (tvchain)
    40664187    {
     4188        VERBOSE(VB_RECORD, LOC + "SPLIT: Creating LiveTV RingBuffer");
    40674189        bool ok;
    40684190        if (!ringBuffer)
    40694191        {
     
    40714193            SetFlags(kFlagRingBufferReady);
    40724194        }
    40734195        else
    4074             ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && recorder);
     4196            ok = SwitchLiveTVRingBuffer(true, !had_dummyrec && newRecorder);
    40754197        if (!ok)
    40764198        {
    40774199            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create RingBuffer 2");
     
    40834205    if (lastTuningRequest.flags & kFlagRecording)
    40844206    {
    40854207        SetRingBuffer(new RingBuffer(rec->GetFileName(), true));
    4086         if (!ringBuffer->IsOpen())
     4208        if (!newRingBuffer->IsOpen())
    40874209        {
    40884210            VERBOSE(VB_IMPORTANT, LOC_ERR +
    40894211                    QString("RingBuffer '%1' not open...")
     
    40944216        }
    40954217    }
    40964218
    4097     if (!ringBuffer)
     4219    if (!newRingBuffer)
    40984220    {
    40994221        VERBOSE(VB_IMPORTANT, LOC_ERR + QString(
    4100                     "Failed to start recorder!  ringBuffer is NULL\n"
     4222                    "Failed to start recorder!  newRingBuffer is NULL\n"
    41014223                    "\t\t\t\t  Tuning request was %1\n")
    41024224                .arg(lastTuningRequest.toString()));
    41034225
     
    41524274        channel->Open(); // Needed because of NVR::MJPEGInit()
    41534275
    41544276    if (rec)
    4155         recorder->SetRecording(rec);
     4277        newRecorder->SetRecording(rec);
     4278
     4279    DoneAddingRecording();
    41564280
    41574281    // Setup for framebuffer capture devices..
    41584282    if (channel)
     
    42194343
    42204344    SwitchLiveTVRingBuffer(true, !had_dummyrec);
    42214345
    4222     recorderMux->Reset();
     4346    newRecorder->Reset();
    42234347    if (had_dummyrec)
    42244348    {
    4225         recorder->SetRingBuffer(ringBuffer);
     4349        newRecorder->SetRingBuffer(newRingBuffer);
    42264350        ProgramInfo *progInfo = tvchain->GetProgramAt(-1);
    4227         recorder->SetRecording(progInfo);
     4351        newRecorder->SetRecording(progInfo);
    42284352        delete progInfo;
    42294353    }
    42304354
     
    45034627    tvchain->AppendNewProgram(pginfo, channel->GetCurrentName(),
    45044628                              channel->GetCurrentInput(), discont);
    45054629
    4506     if (set_rec && recorder)
     4630    if (set_rec && newRecorder)
    45074631    {
    4508         recorder->SetNextRecording(pginfo, rb);
     4632        newRecorder->SetNextRecording(pginfo, rb);
    45094633        if (discont)
    4510             recorder->CheckForRingBufferSwitch();
     4634            newRecorder->CheckForRingBufferSwitch();
    45114635        delete pginfo;
    45124636        SetFlags(kFlagRingBufferReady);
    45134637    }
     
    45224646    return true;
    45234647}
    45244648
     4649void TVRec::DoneAddingRecording()
     4650{
     4651    VERBOSE(VB_RECORD, LOC + QString("Unlocking newRecordingLock for %1")
     4652                                .arg(newRecording->title));
     4653    curRecordings.append(newRecording);
     4654    curRecordings.Sort(comp_recend);
     4655    recordEndTime = GetRecordEndTime(curRecordings.getFirst());
     4656    ringBuffers[newRecording] = newRingBuffer;
     4657    recorders[newRecording] = newRecorder;
     4658    newRecording = NULL;
     4659    newRingBuffer = NULL;
     4660    newRecorder = NULL;
     4661    newRecordingLock.unlock();
     4662}
     4663
    45254664QString TuningRequest::toString(void) const
    45264665{
    45274666    return QString("Program(%1) channel(%2) input(%3) flags(%4)")
  • libs/libmythtv/recorderbase.h

    old new  
    5757     */
    5858    void SetRingBuffer(RingBuffer *rbuf);
    5959
     60    /** \brief StopRecording() removes this recorder from the list of
     61     *         current recorders in RecorderMuxBase recorder list.
     62     */
     63    virtual void StopRecording();
     64
    6065    /** \brief Set an specific option.
    6166     *
    6267     *   Base options include: codec, audiodevice, videodevice, vbidevice,
  • libs/libmythtv/recordermuxbase.h

    old new  
    3838    RecorderMuxBase(TVRec *rec);
    3939    virtual ~RecorderMuxBase();
    4040
     41    void RemoveRecording(RecorderBase *rec);
     42
    4143    /// \brief Sets the video frame rate.
    4244    void SetFrameRate(double rate)
    4345    {
     
    157159    virtual bool PauseAndWait(int timeout = 100);
    158160
    159161    TVRec         *tvrec;
    160     RecorderBase  *recorder;    // SPLIT this should be a QPtrList<RecorderBase>
     162    QPtrList<RecorderBase>  recorders;
     163    QMutex                  recLock;
    161164
    162165    QString        audiodevice;
    163166    QString        videodevice;
  • libs/libmythtv/recorderbase.cpp

    old new  
    101101                    "SetStrOption(...%1): Option not in profile.").arg(name));
    102102}
    103103
     104void RecorderBase::StopRecording()
     105{
     106    recMux->RemoveRecording(this);
     107}
     108
    104109void RecorderBase::CheckForRingBufferSwitch(void)
    105110{
    106111    nextRingBufferLock.lock();
  • libs/libmythtv/recordermuxbase.cpp

    old new  
    1313#define LOC_ERR QString("RecMuxBase(%1) Error: ").arg(videodevice)
    1414
    1515RecorderMuxBase::RecorderMuxBase(TVRec *rec)
    16     : tvrec(rec), recorder(NULL),
     16    : tvrec(rec),
    1717      audiodevice("/dev/dsp"), videodevice("/dev/video"), vbidevice("/dev/vbi"),
    1818      vbimode(0), ntsc(true), ntsc_framerate(true), video_frame_rate(29.97),
    1919      request_pause(false), paused(false)
     
    2424
    2525RecorderMuxBase::~RecorderMuxBase(void)
    2626{
     27    recLock.lock();
     28    recorders.setAutoDelete(true);
     29    recLock.unlock();
     30}
     31
     32void RecorderMuxBase::RemoveRecording(RecorderBase *rec)
     33{
     34    QMutexLocker locker(&recLock);
     35
     36    QString msg = QString("Trying to remove %1 from:").arg((unsigned int)rec);
     37    for (RecorderBase *r = recorders.first(); r; r = recorders.next())
     38        msg += QString("\n%1").arg((unsigned int)r);
     39    VERBOSE(VB_RECORD, msg);
     40
     41    rec->FinishRecording();
     42    recorders.remove(rec);
     43    if (recorders.isEmpty())
     44        StopRecording();
    2745}
    2846
    2947void RecorderMuxBase::SetOption(const QString &name, const QString &value)
  • libs/libmythtv/programinfo.cpp

    old new  
    15241524                           const ProgramInfo        *pg,
    15251525                           const ScheduledRecording *schd)
    15261526{
     1527    VERBOSE(VB_RECORD, QString("Inserting \"%1\" into recorded").arg(pg->title));
    15271528    query.prepare("LOCK TABLES recorded WRITE");
    15281529    if (!query.exec())
    15291530    {
     
    38933894 *                                                                           *
    38943895 * ************************************************************************* */
    38953896
     3897void ProgramList::ToStringList(QStringList &list) const
     3898{
     3899    char tmp[64];
     3900
     3901    // you can't iterate over a const QPtrList, copy it and iterate over
     3902    // the copy to keep this function const
     3903    ProgramList t(*this);
     3904
     3905    INT_TO_LIST(t.count());
     3906    for (ProgramInfo *pginfo = t.first(); pginfo; pginfo = t.next())
     3907    {
     3908        pginfo->ToStringList(list);
     3909    }
     3910}
     3911
     3912bool ProgramList::FromStringList(QStringList &list, int offset)
     3913{
     3914    QStringList::iterator it = list.at(offset);
     3915    return FromStringList(list, it);
     3916}
     3917
     3918bool ProgramList::FromStringList(QStringList &list, QStringList::iterator &it)
     3919{
     3920    const char *listerror = "ProgramList::FromStringList, not enough items "
     3921                            "in list.\n";
     3922    QStringList::iterator listend = list.end();
     3923    QString ts;
     3924    int progCount;
     3925
     3926    INT_FROM_LIST(progCount)
     3927
     3928    for (int i = 0; i < progCount; i++)
     3929    {
     3930        ProgramInfo *pginfo = new ProgramInfo;
     3931        pginfo->FromStringList(list, it);
     3932        append(pginfo);
     3933    }
     3934
     3935    return true;
     3936}
     3937
    38963938bool ProgramList::FromScheduler(bool &hasConflicts, QString rectable,
    38973939                                int recordid)
    38983940{
  • libs/libmythtv/programinfo.h

    old new  
    338338        return at(index);
    339339    };
    340340
     341    void ToStringList(QStringList &list) const;
     342    bool FromStringList(QStringList &list, int offset);
     343    bool FromStringList(QStringList &list, QStringList::iterator &it);
     344
    341345    bool FromScheduler(bool &hasConflicts, QString altTable = "", int recordid=-1);
    342346    bool FromScheduler(void) {
    343347        bool dummyConflicts;
  • libs/libmythtv/mpegrecorder.cpp

    old new  
    4040#endif
    4141}
    4242
    43 #define LOC QString("MPEGRec(%1): ").arg(videodevice)
    44 #define LOC_ERR QString("MPEGRec(%1) Error: ").arg(videodevice)
     43#define LOC QString("MPEGRec(%1): ").arg((unsigned int)this)
     44#define LOC_ERR QString("MPEGRec(%1) Error: ").arg((unsigned int)this)
    4545
    4646MpegRecorder::MpegRecorder(TVRec *rec, MpegRecorderMux *mux) :
    4747    RecorderBase(rec, mux),
     
    5353    // Position map support
    5454    positionMapLock(false)
    5555{
     56    VERBOSE(VB_RECORD, LOC + QString("MpegRecorder ctor"));
    5657}
    5758
    5859MpegRecorder::~MpegRecorder()
  • libs/libmythtv/mpegrecordermux.cpp

    old new  
    483483        if (PauseAndWait(100))
    484484            continue;
    485485
    486         if ((deviceIsMpegFile) && (dynamic_cast<MpegRecorder*>(recorder)->framesWritten))
     486        // This code limits the rate at which frames are written from an MPEG
     487        // file.  Use a local count of the total number of frames written by
     488        // this mux thread.
     489        if (deviceIsMpegFile && framesWritten)
    487490        {
    488491            elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
    489             while ((dynamic_cast<MpegRecorder*>(recorder)->framesWritten / elapsed) > 30)
     492            while ((framesWritten / elapsed) > 30)
    490493            {
    491494                usleep(50000);
    492495                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
     
    554557        }
    555558    }
    556559
    557     recorder->FinishRecording();
    558 
    559560    delete[] buffer;
    560561    recording = false;
    561562
     
    564565
    565566RecorderBase *MpegRecorderMux::CreateNewRecorder(TVRec *tvrec)
    566567{
    567     recorder = new MpegRecorder(tvrec, this);
    568     return recorder;
     568    MpegRecorder *rec = new MpegRecorder(tvrec, this);
     569    recLock.lock();
     570    recorders.append(rec);
     571    recLock.unlock();
     572    return rec;
    569573}
    570574
    571575bool MpegRecorderMux::SetupRecording(void)
    572576{
    573577    leftovers = 0xFFFFFFFF;
    574     VERBOSE(VB_RECORD, QString("recorder = %1").arg((int)recorder));
    575     dynamic_cast<MpegRecorder*>(recorder)->numgops = 0;
    576     dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = 0;
     578    VERBOSE(VB_RECORD, QString("recorder = %1").arg((unsigned int)this));
    577579    return true;
    578580}
    579581
     
    591593
    592594    while (bufptr < buffer + len)
    593595    {
     596        recLock.lock();
     597
    594598        v = *bufptr++;
    595599        if (state == 0x000001)
    596600        {
     
    598602           
    599603            if (state == PACK_HEADER)
    600604            {
    601                 long long startpos = recorder->ringBuffer->GetWritePosition();
    602                 startpos += buildbuffersize + bufptr - bufstart - 4;
    603                 dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos = startpos;
     605                long long startpos = buildbuffersize + bufptr - bufstart - 4;
     606
     607                for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());             rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     608                {
     609                    rec->lastpackheaderpos = rec->ringBuffer->GetWritePosition() + startpos;
     610                }
    604611
    605612                int curpos = bufptr - bufstart - 4;
    606613                if (curpos < 0)
     
    608615                    // header was split
    609616                    buildbuffersize += curpos;
    610617                    if (buildbuffersize > 0)
    611                         recorder->ringBuffer->Write(buildbuffer, buildbuffersize);
     618                    {
     619                        for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());              rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     620                        {
     621                            rec->ringBuffer->Write(buildbuffer, buildbuffersize);
     622                        }
     623                    }
    612624
    613625                    buildbuffersize = 4;
    614626                    memcpy(buildbuffer, &state, 4);
     
    625637                    leftlen -= curpos;
    626638
    627639                    if (buildbuffersize > 0)
    628                         recorder->ringBuffer->Write(buildbuffer, buildbuffersize);
     640                    {
     641                        for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());              rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     642                        {
     643                            rec->ringBuffer->Write(buildbuffer, buildbuffersize);
     644                        }
     645                    }
    629646
    630647                    buildbuffersize = 0;
    631648                }
     
    633650
    634651            if (state == SEQ_START)
    635652            {
    636                 dynamic_cast<MpegRecorder*>(recorder)->lastseqstart = dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos;
     653                for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());              rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     654                {
     655                    rec->lastseqstart = rec->lastpackheaderpos;
     656                }
    637657            }
    638658
    639             if (state == GOP_START && dynamic_cast<MpegRecorder*>(recorder)->lastseqstart == dynamic_cast<MpegRecorder*>(recorder)->lastpackheaderpos)
     659            for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());              rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
    640660            {
    641                 dynamic_cast<MpegRecorder*>(recorder)->framesWritten = dynamic_cast<MpegRecorder*>(recorder)->numgops * keyframedist;
    642                 dynamic_cast<MpegRecorder*>(recorder)->numgops++;
    643                 dynamic_cast<MpegRecorder*>(recorder)->HandleKeyframe();
     661                if (state == GOP_START &&
     662                    rec->lastseqstart == rec->lastpackheaderpos)
     663                {
     664                    if (rec == dynamic_cast<MpegRecorder*>(recorders.getFirst()))
     665                    {
     666                        // count the number of frames written by this mux
     667                        framesWritten = numgops * keyframedist;
     668                        numgops++;
     669                    }
     670
     671                    rec->framesWritten = rec->numgops * keyframedist;
     672                    rec->numgops++;
     673                    rec->HandleKeyframe();
     674                }
    644675            }
    645676        }
    646677        else
    647678            state = ((state << 8) | v) & 0xFFFFFF;
     679
     680        recLock.unlock();
    648681    }
    649682
    650683    leftovers = state;
    651684
    652685    if (buildbuffersize + leftlen > kBuildBufferMaxSize)
    653686    {
    654         recorder->ringBuffer->Write(buildbuffer, buildbuffersize);
     687        recLock.lock();
     688        for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());
     689             rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     690        {
     691            rec->ringBuffer->Write(buildbuffer, buildbuffersize);
     692        }
     693        recLock.unlock();
    655694        buildbuffersize = 0;
    656695    }
    657696
     
    667706
    668707void MpegRecorderMux::Reset(void)
    669708{
    670     dynamic_cast<MpegRecorder*>(recorder)->Reset();
     709    // reset all recorders
     710    recLock.lock();
     711    for (MpegRecorder *rec = dynamic_cast<MpegRecorder*>(recorders.first());
     712         rec; rec = dynamic_cast<MpegRecorder*>(recorders.next()))
     713    {
     714        rec->Reset();
     715    }
     716    recLock.unlock();
    671717
    672718    leftovers = 0xFFFFFFFF;
    673719    buildbuffersize = 0;
  • libs/libmythtv/dtvrecordermux.cpp

    old new  
    4444    // TS packet buffer
    4545    _buffer(0),                     _buffer_size(0)
    4646{
     47    recorder = NULL;
    4748}
    4849
    4950DTVRecorderMux::~DTVRecorderMux()
  • libs/libmythtv/dtvrecordermux.h

    old new  
    5656    // packet buffer
    5757    unsigned char* _buffer;
    5858    int            _buffer_size;
     59
     60    // SPLIT remove list once coverted
     61    RecorderBase *recorder;
    5962};
    6063
    6164#endif // DTVRECORDERMUX_H
  • libs/libmythtv/NuppelVideoRecorderMux.cpp

    old new  
    123123
    124124    go7007 = false;
    125125    resetcapture = false;
     126
     127    recorder = NULL;
    126128}
    127129
    128130NuppelVideoRecorderMux::~NuppelVideoRecorderMux(void)
  • libs/libmythtv/NuppelVideoRecorderMux.h

    old new  
    195195
    196196    bool go7007;
    197197    bool resetcapture;
     198
     199    // SPLIT delete this
     200    RecorderBase *recorder;
    198201};
    199202
    200203#endif
  • programs/mythbackend/encoderlink.cpp

    old new  
    162162 *  \brief Returns true if rec is actually being recorded by TVRec.
    163163 * 
    164164 *   This waits for TVRec to enter a state other than kState_ChangingState
    165  *   Then it checks TVRec::GetRecording() against rec.
    166  *  \param rec Recording to check against TVRec::GetRecording().
     165 *   Then it checks TVRec::GetRecordings() against rec.
     166 *  \param rec Recording to check against TVRec::GetRecordings().
    167167 *  \sa IsRecording(const ProgramInfo*)
    168168 */
    169169bool EncoderLink::MatchesRecording(const ProgramInfo *rec)
    170170{
    171171    bool retval = false;
    172     ProgramInfo *tvrec = NULL;
     172    ProgramList tvrecList;
    173173
    174174    if (local)
    175175    {
     
    177177            usleep(100);
    178178
    179179        if (IsBusyRecording())
    180             tvrec = tv->GetRecording();
     180            tvrecList = tv->GetRecordings();
    181181
    182         if (tvrec)
     182        for (ProgramInfo *tvrec = tvrecList.first(); tvrec; tvrec = tvrecList.current())
    183183        {
    184184            if (tvrec->chanid == rec->chanid &&
    185185                tvrec->recstartts == rec->recstartts)
     
    187187                retval = true;
    188188            }
    189189
     190            tvrecList.removeFirst();
    190191            delete tvrec;
    191192        }
    192193    }
     
    394395 *
    395396 *  \return +1 if the recording started successfully,
    396397 *          -1 if TVRec is busy doing something else, 0 otherwise.
    397  *  \sa RecordPending(const ProgramInfo*, int), StopRecording()
     398 *  \sa RecordPending(const ProgramInfo*, int), StopRecording(ProgramInfo *)
    398399 */
    399400RecStatusType EncoderLink::StartRecording(const ProgramInfo *rec)
    400401{
     
    424425    return retval;
    425426}
    426427
    427 /** \fn EncoderLink::GetRecording()
    428  *  \brief Returns TVRec's current recording.
     428/** \fn EncoderLink::GetRecordings()
     429 *  \brief Returns TVRec's current recordings.
    429430 *
    430  *   Caller is responsible for deleting the ProgramInfo when done with it.
     431 *   Caller is responsible for deleting the %ProgramInfo items in the
     432 *   %ProgramList when done with it.
    431433 *  \return Returns TVRec's current recording if it succeeds, NULL otherwise.
    432434 */
    433 ProgramInfo *EncoderLink::GetRecording(void)
     435ProgramList EncoderLink::GetRecordings(void)
    434436{
    435     ProgramInfo *info = NULL;
    436 
    437437    if (local)
    438         info = tv->GetRecording();
     438        return tv->GetRecordings();
    439439    else if (sock)
    440         info = sock->GetRecording(m_capturecardnum);
    441 
    442     return info;
     440        return sock->GetRecordings(m_capturecardnum);
     441    else
     442        return ProgramList(false);
    443443}
    444444
    445 /** \fn EncoderLink::StopRecording()
     445/** \fn EncoderLink::StopRecording(ProgramInfo *)
    446446 *  \brief Tells TVRec to stop recording immediately.
    447447 *         <b>This only works on local recorders.</b>
    448448 *  \sa StartRecording(const ProgramInfo *rec), FinishRecording()
    449449 */
    450 void EncoderLink::StopRecording(void)
     450void EncoderLink::StopRecording(ProgramInfo *rec)
    451451{
    452452    endRecordingTime = QDateTime::currentDateTime().addDays(-2);
    453453    startRecordingTime = endRecordingTime;
     
    455455
    456456    if (local)
    457457    {
    458         tv->StopRecording();
     458        tv->StopRecording(rec);
    459459        return;
    460460    }
    461461}
     
    463463/** \fn EncoderLink::FinishRecording()
    464464 *  \brief Tells TVRec to stop recording, but only after "overrecord" seconds.
    465465 *         <b>This only works on local recorders.</b>
    466  *  \sa StopRecording()
     466 *  \sa StopRecording(ProgramInfo *)
    467467 */
    468468void EncoderLink::FinishRecording(void)
    469469{
  • programs/mythbackend/encoderlink.h

    old new  
    5959    bool MatchesRecording(const ProgramInfo *rec);
    6060    void RecordPending(const ProgramInfo *rec, int secsleft);
    6161    RecStatusType StartRecording(const ProgramInfo *rec);
    62     void StopRecording(void);
     62    void StopRecording(ProgramInfo *rec);
    6363    void FinishRecording(void);
    6464    void FrontendReady(void);
    6565    void CancelNextRecording(bool);
    6666    bool WouldConflict(const ProgramInfo *rec);
    6767
    6868    bool IsReallyRecording(void);
    69     ProgramInfo *GetRecording(void);
     69    ProgramList GetRecordings(void);
    7070    float GetFramerate(void);
    7171    long long GetFramesWritten(void);
    7272    long long GetFilePosition(void);
  • programs/mythbackend/mainserver.cpp

    old new  
    10111011                       "LEFT JOIN record ON recorded.recordid = record.recordid "
    10121012                       "LEFT JOIN channel ON recorded.chanid = channel.chanid "
    10131013                       "LEFT JOIN recordedprogram ON (recorded.chanid = recordedprogram.chanid "
    1014                               "AND recorded.starttime = recordedprogram.starttime) "
     1014                              "AND recorded.starttime = recordedprogram.starttime "
     1015                              "AND recorded.title = recordedprogram.title) "
    10151016                       "WHERE (recorded.deletepending = 0 OR "
    10161017                              "DATE_ADD(recorded.lastmodified, "
    10171018                                       "INTERVAL 5 MINUTE) <= NOW()) "
     
    15661567
    15671568            if (num > 0)
    15681569            {
    1569                 (*encoderList)[num]->StopRecording();
     1570                (*encoderList)[num]->StopRecording(pginfo);
    15701571                pginfo->recstatus = rsRecorded;
    15711572                if (m_sched)
    15721573                    m_sched->UpdateRecStatus(pginfo);
     
    16051606        {
    16061607            recnum = iter.key();
    16071608
    1608             elink->StopRecording();
     1609            elink->StopRecording(pginfo);
    16091610
    16101611            while (elink->IsBusyRecording() ||
    16111612                   elink->GetState() == kState_ChangingState)
     
    16651666
    16661667            if (num > 0)
    16671668            {
    1668                 (*encoderList)[num]->StopRecording();
     1669                (*encoderList)[num]->StopRecording(pginfo);
    16691670                pginfo->recstatus = rsRecorded;
    16701671                if (m_sched)
    16711672                    m_sched->UpdateRecStatus(pginfo);
     
    16951696        {
    16961697            resultCode = iter.key();
    16971698
    1698             elink->StopRecording();
     1699            elink->StopRecording(pginfo);
    16991700
    17001701            while (elink->IsBusyRecording() ||
    17011702                   elink->GetState() == kState_ChangingState)
     
    24372438        long long value = enc->GetMaxBitrate();
    24382439        encodeLongLong(retlist, value);
    24392440    }
    2440     else if (command == "GET_CURRENT_RECORDING")
     2441    else if (command == "GET_CURRENT_RECORDINGS")
    24412442    {
    2442         ProgramInfo *info = enc->GetRecording();
    2443         info->ToStringList(retlist);
    2444         delete info;
     2443        ProgramList info = enc->GetRecordings();
     2444        info.ToStringList(retlist);
     2445
     2446        for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next())
     2447            delete pginfo;
    24452448    }
    24462449    else if (command == "GET_KEYFRAME_POS")
    24472450    {
     
    24682471        if (!retlist.size())
    24692472            retlist << "ok";
    24702473    }
    2471     else if (command == "GET_RECORDING")
     2474    else if (command == "GET_RECORDINGS")
    24722475    {
    2473         ProgramInfo *pginfo = enc->GetRecording();
    2474         if (pginfo)
    2475         {
    2476             pginfo->ToStringList(retlist);
     2476        ProgramList info = enc->GetRecordings();
     2477        info.ToStringList(retlist);
     2478
     2479        for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next())
    24772480            delete pginfo;
    2478         }
    2479         else
    2480         {
    2481             ProgramInfo dummy;
    2482             dummy.ToStringList(retlist);
    2483         }
    24842481    }
    24852482    else if (command == "FRONTEND_READY")
    24862483    {
     
    27862783        long long value = enc->GetMaxBitrate();
    27872784        encodeLongLong(retlist, value);
    27882785    }
    2789     else if (command == "GET_CURRENT_RECORDING")
     2786    else if (command == "GET_CURRENT_RECORDINGS")
    27902787    {
    2791         ProgramInfo *info = enc->GetRecording();
    2792         info->ToStringList(retlist);
    2793         delete info;
     2788        ProgramList info = enc->GetRecordings();
     2789        info.ToStringList(retlist);
     2790
     2791        for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next())
     2792            delete pginfo;
    27942793    }
    27952794
    27962795    SendResponse(pbssock, retlist);
     
    36983697    {
    36993698        EncoderLink *elink = iter.data();
    37003699        elink->CancelNextRecording(true);
    3701         ProgramInfo *pinfo = elink->GetRecording();
    3702         pinfo->ToStringList(strlist);
    3703         delete pinfo;
     3700        ProgramList info = elink->GetRecordings();
     3701        info.ToStringList(strlist);
     3702
     3703        for (ProgramInfo *pginfo = info.first(); pginfo; pginfo = info.next())
     3704            delete pginfo;
    37043705    }
    37053706
    37063707    WriteStringList(masterServerSock, strlist);
     
    38703871                case kState_RecordingOnly:
    38713872                case kState_WatchingRecording:
    38723873                {
    3873                     ProgramInfo *pInfo = elink->GetRecording();
     3874                    ProgramList info = elink->GetRecordings();
    38743875
    3875                     if (pInfo)
     3876                    for (ProgramInfo *pInfo = info.first(); pInfo; pInfo = info.next())
    38763877                    {
    38773878                        FillProgramInfo(pDoc, encoder, pInfo);
    38783879                        delete pInfo;
  • programs/mythbackend/playbacksock.cpp

    old new  
    217217    return ret;
    218218}
    219219
    220 /** \fn *PlaybackSock::GetRecording(int)
    221  *  \brief Returns the ProgramInfo being used by any current recording.
     220/** \fn *PlaybackSock::GetRecordings(int)
     221 *  \brief Returns the ProgramList being used by any current recording.
    222222 *
    223  *   Caller is responsible for deleting the ProgramInfo when done with it.
     223 *   Caller is responsible for deleting the ProgramInfo in the ProgramList
     224 *   when done with it.
    224225 *  \param capturecardnum cardid of recorder
    225226 */
    226 ProgramInfo *PlaybackSock::GetRecording(int capturecardnum)
     227ProgramList PlaybackSock::GetRecordings(int capturecardnum)
    227228{
    228229    QStringList strlist = QString("QUERY_REMOTEENCODER %1")
    229230        .arg(capturecardnum);
    230231
    231     strlist << "GET_CURRENT_RECORDING";
     232    strlist << "GET_CURRENT_RECORDINGS";
    232233
    233234    SendReceiveStringList(strlist);
    234235
    235     ProgramInfo *info = new ProgramInfo();
    236     info->FromStringList(strlist, 0);
     236    ProgramList info(false);
     237    info.FromStringList(strlist, 0);
    237238    return info;
    238239}
    239240
  • programs/mythbackend/playbacksock.h

    old new  
    5454    bool IsBusy(int capturecardnum);
    5555    int GetEncoderState(int capturecardnum);
    5656    long long GetMaxBitrate(int capturecardnum);
    57     ProgramInfo *GetRecording(int capturecardnum);
     57    ProgramList GetRecordings(int capturecardnum);
    5858    bool EncoderIsRecording(int capturecardnum, const ProgramInfo *pginfo);
    5959    RecStatusType StartRecording(int capturecardnum,
    6060                                 const ProgramInfo *pginfo);