示例#1
0
DTC::LiveStreamInfo *Content::AddRecordingLiveStream( int              nChanId,
                                                      const QDateTime &dtStartTime,
                                                      int              nMaxSegments,
                                                      int              nWidth,
                                                      int              nHeight,
                                                      int              nBitrate,
                                                      int              nAudioBitrate,
                                                      int              nSampleRate )
{
    if (!dtStartTime.isValid())
        throw( "StartTime is invalid" );

    // ------------------------------------------------------------------
    // Read Recording From Database
    // ------------------------------------------------------------------

    ProgramInfo pginfo( (uint)nChanId, dtStartTime );

    if (!pginfo.GetChanID())
    {
        LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed")
                                    .arg( nChanId )
                                    .arg( dtStartTime.toString() ));
        return NULL;
    }

    if ( pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        // We only handle requests for local resources

        QString sMsg =
            QString("GetRecording: Wrong Host '%1' request from '%2'.")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sFileName( GetPlaybackURL(&pginfo) );

    // ----------------------------------------------------------------------
    // check to see if the file exists
    // ----------------------------------------------------------------------

    if (!QFile::exists( sFileName ))
    {
        LOG( VB_UPNP, LOG_ERR, QString("AddRecordingLiveStream - for %1, %2 failed")
                                    .arg( nChanId )
                                    .arg( dtStartTime.toString() ));
        return NULL;
    }

    QFileInfo fInfo( sFileName );

    return AddLiveStream( pginfo.GetStorageGroup(), fInfo.fileName(),
                          pginfo.GetHostname(), nMaxSegments, nWidth,
                          nHeight, nBitrate, nAudioBitrate, nSampleRate );
}
示例#2
0
QFileInfo Content::GetRecording( int              nChanId,
                                 const QDateTime &recstarttsRaw )
{
    if (!recstarttsRaw.isValid())
        throw( "StartTime is invalid" );

    // ------------------------------------------------------------------
    // Read Recording From Database
    // ------------------------------------------------------------------

    QDateTime recstartts = recstarttsRaw.toUTC();

    ProgramInfo pginfo((uint)nChanId, recstartts);

    if (!pginfo.GetChanID())
    {
        LOG(VB_UPNP, LOG_ERR, QString("GetRecording - for '%1' failed")
            .arg(ProgramInfo::MakeUniqueKey(nChanId, recstartts)));

        return QFileInfo();
    }

    if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        // We only handle requests for local resources

        QString sMsg =
            QString("GetRecording: Wrong Host '%1' request from '%2'.")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sFileName( GetPlaybackURL(&pginfo) );

    // ----------------------------------------------------------------------
    // check to see if the file exists
    // ----------------------------------------------------------------------

    if (QFile::exists( sFileName ))
        return QFileInfo( sFileName );

    return QFileInfo();
}
示例#3
0
QString FileServerHandler::LocalFilePath(const QUrl &url,
                                           const QString &wantgroup)
{
    QString lpath = url.path();

    if (lpath.section('/', -2, -2) == "channels")
    {
        // This must be an icon request. Check channel.icon to be safe.
        QString querytext;

        QString file = lpath.section('/', -1);
        lpath = "";

        MSqlQuery query(MSqlQuery::InitCon());
        query.prepare("SELECT icon FROM channel WHERE icon LIKE :FILENAME ;");
        query.bindValue(":FILENAME", QString("%/") + file);

        if (query.exec() && query.next())
        {
            lpath = query.value(0).toString();
        }
        else
        {
            MythDB::DBError("Icon path", query);
        }
    }
    else
    {
        lpath = lpath.section('/', -1);

        QString fpath = lpath;
        if (fpath.right(4) == ".png")
            fpath = fpath.left(fpath.length() - 4);

        ProgramInfo pginfo(fpath);
        if (pginfo.GetChanID())
        {
            QString pburl = GetPlaybackURL(&pginfo);
            if (pburl.left(1) == "/")
            {
                lpath = pburl.section('/', 0, -2) + "/" + lpath;
                LOG(VB_FILE, LOG_INFO,
                    QString("Local file path: %1").arg(lpath));
            }
            else
            {
                LOG(VB_GENERAL, LOG_ERR,
                        QString("LocalFilePath unable to find local "
                                "path for '%1', found '%2' instead.")
                                .arg(lpath).arg(pburl));
                lpath = "";
            }
        }
        else if (!lpath.isEmpty())
        {
            // For securities sake, make sure filename is really the pathless.
            QString opath = lpath;
            StorageGroup sgroup;

            if (!wantgroup.isEmpty())
            {
                sgroup.Init(wantgroup);
                lpath = url.toString();
            }
            else
            {
                lpath = QFileInfo(lpath).fileName();
            }

            QString tmpFile = sgroup.FindFile(lpath);
            if (!tmpFile.isEmpty())
            {
                lpath = tmpFile;
                LOG(VB_FILE, LOG_INFO,
                        QString("LocalFilePath(%1 '%2'), found through "
                                "exhaustive search at '%3'")
                            .arg(url.toString()).arg(opath).arg(lpath));
            }
            else
            {
                LOG(VB_GENERAL, LOG_ERR, QString("LocalFilePath unable to "
                                                 "find local path for '%1'.")
                                .arg(opath));
                lpath = "";
            }

        }
        else
        {
            lpath = "";
        }
    }

    return lpath;
}
示例#4
0
QFileInfo Content::GetPreviewImage(        int        nChanId,
                                     const QDateTime &recstarttsRaw,
                                           int        nWidth,
                                           int        nHeight,
                                           int        nSecsIn )
{
    if (!recstarttsRaw.isValid())
    {
        QString sMsg = QString("GetPreviewImage: bad start time '%1'")
            .arg(MythDate::toString(recstarttsRaw, MythDate::ISODate));

        LOG(VB_GENERAL, LOG_ERR, sMsg);

        throw sMsg;
    }

    QDateTime recstartts = recstarttsRaw.toUTC();

    // ----------------------------------------------------------------------
    // Read Recording From Database
    // ----------------------------------------------------------------------

    ProgramInfo pginfo( (uint)nChanId, recstartts);

    if (!pginfo.GetChanID())
    {
        LOG(VB_GENERAL, LOG_ERR,
            QString("GetPreviewImage: No recording for '%1'")
            .arg(ProgramInfo::MakeUniqueKey(nChanId, recstartts)));
        return QFileInfo();
    }

    if (pginfo.GetHostname().toLower() != gCoreContext->GetHostName().toLower())
    {
        QString sMsg =
            QString("GetPreviewImage: Wrong Host '%1' request from '%2'")
                          .arg( gCoreContext->GetHostName())
                          .arg( pginfo.GetHostname() );

        LOG(VB_UPNP, LOG_ERR, sMsg);

        throw HttpRedirectException( pginfo.GetHostname() );
    }

    QString sFileName = GetPlaybackURL(&pginfo);

    // ----------------------------------------------------------------------
    // check to see if default preview image is already created.
    // ----------------------------------------------------------------------

    QString sPreviewFileName;

    if (nSecsIn <= 0)
    {
        nSecsIn = -1;
        sPreviewFileName = sFileName + ".png";
    }
    else
    {
        sPreviewFileName = QString("%1.%2.png").arg(sFileName).arg(nSecsIn);
    }

    if (!QFile::exists( sPreviewFileName ))
    {
        // ------------------------------------------------------------------
        // Must generate Preview Image, Generate Image and save.
        // ------------------------------------------------------------------
        if (!pginfo.IsLocal() && sFileName.startsWith("/"))
            pginfo.SetPathname(sFileName);

        if (!pginfo.IsLocal())
            return QFileInfo();

        PreviewGenerator *previewgen = new PreviewGenerator( &pginfo, 
                                                             QString(), 
                                                             PreviewGenerator::kLocal);
        previewgen->SetPreviewTimeAsSeconds( nSecsIn          );
        previewgen->SetOutputFilename      ( sPreviewFileName );

        bool ok = previewgen->Run();

        previewgen->deleteLater();

        if (!ok)
            return QFileInfo();
    }

    float fAspect = 0.0;

    QImage *pImage = new QImage(sPreviewFileName);

    if (!pImage)
        return QFileInfo();

    if (fAspect <= 0)
        fAspect = (float)(pImage->width()) / pImage->height();

    if (fAspect == 0)
    {
        delete pImage;
        return QFileInfo();
    }

    bool bDefaultPixmap = (nWidth == 0) && (nHeight == 0);

    if ( nWidth == 0 )
        nWidth = (int)rint(nHeight * fAspect);

    if ( nHeight == 0 )
        nHeight = (int)rint(nWidth / fAspect);

    QString sNewFileName;

    if (bDefaultPixmap)
        sNewFileName = sPreviewFileName;
    else
        sNewFileName = QString( "%1.%2.%3x%4.png" )
                          .arg( sFileName )
                          .arg( nSecsIn   )
                          .arg( nWidth    )
                          .arg( nHeight   );

    // ----------------------------------------------------------------------
    // check to see if scaled preview image is already created.
    // ----------------------------------------------------------------------

    if (QFile::exists( sNewFileName ))
    {
        delete pImage;
        return QFileInfo( sNewFileName );
    }

    PreviewGenerator *previewgen = new PreviewGenerator( &pginfo,
                                                         QString(),
                                                         PreviewGenerator::kLocal);
    previewgen->SetPreviewTimeAsSeconds( nSecsIn             );
    previewgen->SetOutputFilename      ( sNewFileName        );
    previewgen->SetOutputSize          (QSize(nWidth,nHeight));

    bool ok = previewgen->Run();

    previewgen->deleteLater();

    if (!ok)
        return QFileInfo();

    delete pImage;

    return QFileInfo( sNewFileName );
}
示例#5
0
/** \fn MythSystemEventHandler::SubstituteMatches(const QStringList &tokens,
                                                  QString &command)
 *  \brief Substitutes %MATCH% variables in given command line.
 *  \sa ProgramInfo::SubstituteMatches(QString &str)
 *
 *  Subsitutes values for %MATCH% type variables in given command string.
 *  Some of these matches come from the tokens list passed in and some
 *  may come from a ProgramInfo if a chanid and starttime are specified
 *  in the tokens list.
 *
 *  \param tokens  Const QStringList containing token list passed with event.
 *  \param command Command line containing %MATCH% variables to be substituted.
 */
void MythSystemEventHandler::SubstituteMatches(const QStringList &tokens,
                                               QString &command)
{
    if (command.isEmpty())
        return;

    LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: BEFORE: %1")
                                            .arg(command));
    QString args;
    uint chanid = 0;
    QDateTime recstartts;
    QString sender;

    QStringList::const_iterator it = tokens.begin();
    ++it;
    command.replace(QString("%EVENTNAME%"), *it);

    ++it;
    while (it != tokens.end())
    {
        if (!args.isEmpty())
            args += " ";
        args += *it;

        // Check for some token names that we substitute one for one as
        // %MATCH% type variables.
        if ((*it == "CARDID") ||
            (*it == "COMMAND") ||
            (*it == "RECSTATUS") ||
            (*it == "HOSTNAME") ||
            (*it == "SECS") ||
            (*it == "SENDER") ||
            (*it == "PATH"))
        {
            QString token = *it;

            if (++it == tokens.end())
                break;

            if (token == "SENDER")
                sender = *it;

            // The following string is broken up on purpose to indicate
            // what we're replacing is the token surrounded by percent signs
            command.replace(QString("%" "%1" "%").arg(token), *it);

            if (!args.isEmpty())
                args += " ";
            args += *it;
        }

        // Remember any chanid and starttime so we can lookup info about
        // the recording from the database.
        if (*it == "CHANID")
        {
            if (++it == tokens.end())
                break;

            chanid = (*it).toUInt();

            if (!args.isEmpty())
                args += " ";
            args += *it;
        }

        if (*it == "STARTTIME")
        {
            if (++it == tokens.end())
                break;

            recstartts = MythDate::fromString(*it);

            if (!args.isEmpty())
                args += " ";
            args += *it;
        }

        ++it;
    }

    command.replace(QString("%ARGS%"), args);

    ProgramInfo pginfo(chanid, recstartts);
    bool pginfo_loaded = pginfo.GetChanID();
    if (!pginfo_loaded)
    {
        RecordingInfo::LoadStatus status;
        pginfo = RecordingInfo(chanid, recstartts, false, 0, &status);
        pginfo_loaded = RecordingInfo::kFoundProgram == status;
    }

    if (pginfo_loaded)
    {
        pginfo.SubstituteMatches(command);
    }
    else
    {
        command.replace(QString("%CHANID%"), QString::number(chanid));
        command.replace(QString("%STARTTIME%"),
                        MythDate::toString(recstartts, MythDate::kFilename));
        command.replace(QString("%STARTTIMEISO%"),
                        recstartts.toString(Qt::ISODate));
    }

    command.replace(QString("%VERBOSELEVEL%"), QString("%1").arg(verboseMask));

    LOG(VB_FILE, LOG_DEBUG, LOC + QString("SubstituteMatches: AFTER : %1")
                                            .arg(command));
}
示例#6
0
uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar, uint32_t dfsr)
{
    struct tcb_s *tcb = this_task();
    uint32_t *savestate;

    /* Save the saved processor context in CURRENT_REGS where it can be accessed
     * for register dumps and possibly context switching.
     */

    savestate    = (uint32_t *)CURRENT_REGS;
    CURRENT_REGS = regs;

    /* In the NuttX on-demand paging implementation, only the read-only, .text
     * section is paged.  However, the ARM compiler generated PC-relative data
     * fetches from within the .text sections.  Also, it is customary to locate
     * read-only data (.rodata) within the same section as .text so that it
     * does not require copying to RAM. Misses in either of these case should
     * cause a data abort.
     *
     * We are only interested in data aborts due to page translations faults.
     * Sections should already be in place and permissions should already be
     * be set correctly (to read-only) so any other data abort reason is a
     * fatal error.
     */

    pginfo("DFSR: %08x DFAR: %08x\n", dfsr, dfar);
    if ((dfsr & FSR_MASK) != FSR_PAGE)
    {
        goto segfault;
    }

    /* Check the (virtual) address of data that caused the data abort. When
     * the exception occurred, this address was provided in the DFAR register.
     * (It has not yet been saved in the register context save area).
     */

    pginfo("VBASE: %08x VEND: %08x\n", PG_PAGED_VBASE, PG_PAGED_VEND);
    if (dfar < PG_PAGED_VBASE || dfar >= PG_PAGED_VEND)
    {
        goto segfault;
    }

    /* Save the offending data address as the fault address in the TCB of
     * the currently task.  This fault address is also used by the prefetch
     * abort handling; this will allow common paging logic for both
     * prefetch and data aborts.
     */

    tcb->xcp.dfar = regs[REG_R15];

    /* Call pg_miss() to schedule the page fill.  A consequences of this
     * call are:
     *
     * (1) The currently executing task will be blocked and saved on
     *     on the g_waitingforfill task list.
     * (2) An interrupt-level context switch will occur so that when
     *     this function returns, it will return to a different task,
     *     most likely the page fill worker thread.
     * (3) The page fill worker task has been signalled and should
     *     execute immediately when we return from this exception.
     */

    pg_miss();

    /* Restore the previous value of CURRENT_REGS.  NULL would indicate that
     * we are no longer in an interrupt handler.  It will be non-NULL if we
     * are returning from a nested interrupt.
     */

    CURRENT_REGS = savestate;
    return regs;

segfault:
    _alert("Data abort. PC: %08x DFAR: %08x DFSR: %08x\n",
           regs[REG_PC], dfar, dfsr);
    PANIC();
    return regs; /* To keep the compiler happy */
}
示例#7
0
void ScheduleCommon::customEvent(QEvent *event)
{
    if (event->type() == DialogCompletionEvent::kEventType)
    {
        DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);

        QString resultid   = dce->GetId();
        QString resulttext = dce->GetResultText();

        if (resultid == "schedulenotscheduled")
        {
            if (!qVariantCanConvert<RecordingInfo>(dce->GetData()))
                return;

            RecordingInfo recInfo = qVariantValue<RecordingInfo>
                (dce->GetData());

            if (resulttext == tr("Record only this showing"))
                recInfo.ApplyRecordStateChange(kSingleRecord);
            else if (resulttext == tr("Record all showings"))
                recInfo.ApplyRecordStateChange(kAllRecord);
            else if (resulttext == tr("Record one showing of this episode"))
            {
                recInfo.ApplyRecordStateChange(kOneRecord, false);
                recInfo.GetRecordingRule()->m_filter |= 64; // This episode
                recInfo.GetRecordingRule()->Save();
            }
            else if (resulttext == tr("Record all showings on this channel"))
            {
                recInfo.ApplyRecordStateChange(kAllRecord, false);
                recInfo.GetRecordingRule()->m_filter |= 1024; // This channel
                recInfo.GetRecordingRule()->Save();
            }
            else if (resulttext == tr("Record with more options"))
            {
                EditScheduled(&recInfo);
            }
        }
        else if (resultid == "schedulenotrecording")
        {
            if (!qVariantCanConvert<RecordingInfo>(dce->GetData()))
                return;

            RecordingInfo recInfo = qVariantValue<RecordingInfo>
                (dce->GetData());

            if (resulttext == tr("Restart recording this showing"))
                recInfo.ReactivateRecording();
            else if (resulttext == tr("Record this showing anyway"))
            {
                recInfo.ApplyRecordStateChange(kOverrideRecord);
                if (recInfo.GetRecordingStartTime() < MythDate::current())
                    recInfo.ReactivateRecording();
            }
            else if (resulttext == tr("Forget previous recording"))
                recInfo.ForgetHistory();
            else if (resulttext == tr("Don't record this showing"))
                recInfo.ApplyRecordStateChange(kDontRecord);
            else if (resulttext == tr("Never record this episode"))
            {
                recInfo.SetRecordingStatus(rsNeverRecord);
                recInfo.SetScheduledStartTime(MythDate::current());
                recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime());
                recInfo.AddHistory(true, true);
            }
            else if (resulttext == tr("Delete override rule") ||
                     resulttext == tr("Delete recording rule"))
                recInfo.ApplyRecordStateChange(kNotRecording);
            else if (resulttext == tr("Edit override options") ||
                     resulttext == tr("Edit recording options"))
            {
                EditScheduled(&recInfo);
            }
            else if (resulttext == tr("Override this showing with options"))
            {
                MakeOverride(&recInfo);
            }
        }
        else if (resultid == "schedulerecording")
        {
            if (!qVariantCanConvert<RecordingInfo>(dce->GetData()))
                return;

            RecordingInfo recInfo = qVariantValue<RecordingInfo>
                                                            (dce->GetData());

            if (resulttext == tr("Restart recording this showing"))
                recInfo.ReactivateRecording();
            else if (resulttext == tr("Stop recording this showing"))
            {
                ProgramInfo pginfo(
                    recInfo.GetChanID(), recInfo.GetRecordingStartTime());
                if (pginfo.GetChanID())
                    RemoteStopRecording(&pginfo);
            }
            else if (resulttext == tr("Don't record this showing"))
                recInfo.ApplyRecordStateChange(kDontRecord);
            else if (resulttext == tr("Never record this episode"))
            {
                recInfo.SetRecordingStatus(rsNeverRecord);
                recInfo.SetScheduledStartTime(MythDate::current());
                recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime());
                recInfo.AddHistory(true, true);
            }
            else if (resulttext == tr("Delete override rule") ||
                     resulttext == tr("Delete recording rule"))
                recInfo.ApplyRecordStateChange(kNotRecording);
            else if (resulttext == tr("Edit options for this showing"))
            {
                if (recInfo.GetRecordingRuleType() == kSingleRecord ||
                    recInfo.GetRecordingRuleType() == kOverrideRecord ||
                    recInfo.GetRecordingRuleType() == kOneRecord)
                    EditScheduled(&recInfo);
                else
                    MakeOverride(&recInfo, true);
            }
            else if (resulttext == tr("Edit override options") ||
                     resulttext == tr("Edit recording options"))
            {
                EditScheduled(&recInfo);
            }
            else if (resulttext == tr("Override this showing with options"))
            {
                MakeOverride(&recInfo);
            }
        }
    }
}
示例#8
0
void up_prefetchabort(uint32_t *regs)
{
#ifdef CONFIG_PAGING
   uint32_t *savestate;

  /* Save the saved processor context in CURRENT_REGS where it can be accessed
   * for register dumps and possibly context switching.
   */

  savestate    = (uint32_t *)CURRENT_REGS;
#endif
  CURRENT_REGS = regs;

#ifdef CONFIG_PAGING
  /* Get the (virtual) address of instruction that caused the prefetch abort.
   * When the exception occurred, this address was provided in the lr register
   * and this value was saved in the context save area as the PC at the
   * REG_R15 index.
   *
   * Check to see if this miss address is within the configured range of
   * virtual addresses.
   */

  pginfo("VADDR: %08x VBASE: %08x VEND: %08x\n",
         regs[REG_PC], PG_PAGED_VBASE, PG_PAGED_VEND);

  if (regs[REG_R15] >= PG_PAGED_VBASE && regs[REG_R15] < PG_PAGED_VEND)
    {
      /* Save the offending PC as the fault address in the TCB of the currently
       * executing task.  This value is, of course, already known in regs[REG_R15],
       * but saving it in this location will allow common paging logic for both
       * prefetch and data aborts.
       */

      struct tcb_s *tcb = this_task();
      tcb->xcp.far  = regs[REG_R15];

      /* Call pg_miss() to schedule the page fill.  A consequences of this
       * call are:
       *
       * (1) The currently executing task will be blocked and saved on
       *     on the g_waitingforfill task list.
       * (2) An interrupt-level context switch will occur so that when
       *     this function returns, it will return to a different task,
       *     most likely the page fill worker thread.
       * (3) The page fill worker task has been signalled and should
       *     execute immediately when we return from this exception.
       */

      pg_miss();

      /* Restore the previous value of CURRENT_REGS.  NULL would indicate that
       * we are no longer in an interrupt handler.  It will be non-NULL if we
       * are returning from a nested interrupt.
       */

      CURRENT_REGS = savestate;
    }
  else
#endif
    {
      _alert("Prefetch abort. PC: %08x\n", regs[REG_PC]);
      PANIC();
    }
}
示例#9
0
void ScheduleCommon::customEvent(QEvent *event)
{
    if (event->type() == DialogCompletionEvent::kEventType)
    {
        DialogCompletionEvent *dce = (DialogCompletionEvent*)(event);

        QString resultid   = dce->GetId();
        QString resulttext = dce->GetResultText();

        if (resultid == "schedulenotrecording")
        {
            if (!qVariantCanConvert<RecordingInfo>(dce->GetData()))
                return;

            RecordingInfo recInfo = qVariantValue<RecordingInfo>
                (dce->GetData());

            if (resulttext == tr("Reactivate"))
                recInfo.ReactivateRecording();
            else if (resulttext == tr("Record anyway"))
            {
                recInfo.ApplyRecordStateChange(kOverrideRecord);
                if (recInfo.GetRecordingStartTime() < QDateTime::currentDateTime())
                    recInfo.ReactivateRecording();
            }
            else if (resulttext == tr("Forget Previous"))
                recInfo.ForgetHistory();
            else if (resulttext == tr("Don't record"))
                recInfo.ApplyRecordStateChange(kDontRecord);
            else if (resulttext == tr("Never record"))
            {
                recInfo.SetRecordingStatus(rsNeverRecord);
                recInfo.SetScheduledStartTime(QDateTime::currentDateTime());
                recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime());
                recInfo.AddHistory(true, true);
            }
            else if (resulttext == tr("Clear Override"))
                recInfo.ApplyRecordStateChange(kNotRecording);
            else if (resulttext == tr("Edit Override") ||
                     resulttext == tr("Edit Options"))
            {
                EditScheduled(&recInfo);
            }
            else if (resulttext == tr("Add Override"))
            {
                MakeOverride(&recInfo);
            }
        }
        else if (resultid == "schedulerecording")
        {
            if (!qVariantCanConvert<RecordingInfo>(dce->GetData()))
                return;
            
            RecordingInfo recInfo = qVariantValue<RecordingInfo>
                                                            (dce->GetData());
            
            if (resulttext == tr("Reactivate"))
                recInfo.ReactivateRecording();
            else if (resulttext == tr("Stop recording"))
            {
                ProgramInfo pginfo(
                    recInfo.GetChanID(), recInfo.GetRecordingStartTime());
                if (pginfo.GetChanID())
                    RemoteStopRecording(&pginfo);
            }
            else if (resulttext == tr("Don't record"))
                recInfo.ApplyRecordStateChange(kDontRecord);
            else if (resulttext == tr("Never record"))
            {
                recInfo.SetRecordingStatus(rsNeverRecord);
                recInfo.SetScheduledStartTime(QDateTime::currentDateTime());
                recInfo.SetScheduledEndTime(recInfo.GetRecordingStartTime());
                recInfo.AddHistory(true, true);
            }
            else if (resulttext == tr("Clear Override"))
                recInfo.ApplyRecordStateChange(kNotRecording);
            else if (resulttext == tr("Modify Recording Options"))
            {
                if (recInfo.GetRecordingRuleType() == kSingleRecord ||
                    recInfo.GetRecordingRuleType() == kOverrideRecord ||
                    recInfo.GetRecordingRuleType() == kFindOneRecord)
                    EditScheduled(&recInfo);
                else
                    MakeOverride(&recInfo, true);
            }
            else if (resulttext == tr("Edit Override") ||
                     resulttext == tr("Edit Options"))
            {
                EditScheduled(&recInfo);
            }
            else if (resulttext == tr("Add Override"))
            {
                MakeOverride(&recInfo);
            }
        }
    }
}