Ticket #8631: seek_honors_cutlist_v6.patch

File seek_honors_cutlist_v6.patch, 27.0 KB (added by Jim Stichnoth <stichnot@…>, 10 years ago)
  • mythtv/libs/libmythtv/deletemap.cpp

    diff --git a/mythtv/libs/libmythtv/deletemap.cpp b/mythtv/libs/libmythtv/deletemap.cpp
    index 7cda7ac..bc42b43 100644
    a b void DeleteMap::UpdateSeekAmount(int change, double framerate) 
    6666    }
    6767}
    6868
    69 /**
     69static QString createTimeString(uint64_t frame, uint64_t total,
     70                                double frame_rate, bool full_resolution)
     71{
     72    int secs   = (int)(frame / frame_rate);
     73    int frames = frame - (int)(secs * frame_rate);
     74    int totalSecs = (int)(total / frame_rate);
     75    QString timestr;
     76    if (totalSecs >= 3600)
     77        timestr = QString::number(secs / 3600) + ":";
     78    timestr += QString("%1").arg((secs / 60) % 60, 2, 10, QChar(48)) +
     79        QString(":%1").arg(secs % 60, 2, 10, QChar(48));
     80    if (full_resolution)
     81        timestr += QString(".%1").arg(frames, 2, 10, QChar(48));
     82    return timestr;
     83}
     84
     85 /**
    7086 * \brief Show and update the edit mode On Screen Display. The cut regions
    7187 *        are only refreshed if the deleteMap has been updated.
    7288 */
    void DeleteMap::UpdateOSD(uint64_t frame, uint64_t total, double frame_rate, 
    84100    infoMap.detach();
    85101    ctx->UnlockPlayingInfo(__FILE__, __LINE__);
    86102
    87     int secs   = (int)(frame / frame_rate);
    88     int frames = frame - (int)(secs * frame_rate);
    89     QString timestr = QString::number(secs / 3600) +
    90                       QString(":%1").arg((secs / 60) % 60, 2, 10, QChar(48)) +
    91                       QString(":%1").arg(secs % 60, 2, 10, QChar(48)) +
    92                       QString(".%1").arg(frames, 2, 10, QChar(48));
    93 
    94103    QString cutmarker = " ";
    95104    if (IsInDelete(frame))
    96105        cutmarker = QObject::tr("cut");
    97106
     107    QString timestr = createTimeString(frame, total, frame_rate, true);
     108    uint64_t relTotal = TranslatePositionAbsToRel(total);
     109    QString relTimeDisplay = createTimeString(TranslatePositionAbsToRel(frame),
     110                                              relTotal, frame_rate, false);
     111    QString relLengthDisplay = createTimeString(relTotal,
     112                                                relTotal, frame_rate, false);
    98113    infoMap["timedisplay"]  = timestr;
    99114    infoMap["framedisplay"] = QString::number(frame);
    100115    infoMap["cutindicator"] = cutmarker;
    101116    infoMap["title"]        = QObject::tr("Edit");
    102117    infoMap["seekamount"]   = m_seekText;;
     118    infoMap["reltimedisplay"] = relTimeDisplay;
     119    infoMap["rellengthdisplay"] = relLengthDisplay;
     120    infoMap["fulltimedisplay"] = timestr + " (" +
     121        QObject::tr("%1 of %2").arg(relTimeDisplay).arg(relLengthDisplay) + ")";
    103122
    104123    QHash<QString,float> posMap;
    105124    posMap.insert("position", (float)((double)frame/(double)total));
    bool DeleteMap::IsSaved(PlayerContext *ctx) 
    721740
    722741    return currentMap == savedMap;
    723742}
     743
     744uint64_t DeleteMap::TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap,
     745                                              uint64_t absPosition)
     746{
     747    uint64_t subtraction = 0;
     748    uint64_t startOfCutRegion = 0;
     749    frm_dir_map_t::const_iterator i;
     750    bool withinCut = false;
     751    bool first = true;
     752    for (i = deleteMap.constBegin();
     753         i != deleteMap.constEnd() && i.key() <= absPosition;
     754         i++)
     755    {
     756        if (first)
     757            withinCut = (i.value() == MARK_CUT_END);
     758        first = false;
     759        if (i.value() == MARK_CUT_START && !withinCut)
     760        {
     761            withinCut = true;
     762            startOfCutRegion = i.key();
     763        }
     764        else if (i.value() == MARK_CUT_END && withinCut)
     765        {
     766            withinCut = false;
     767            subtraction += (i.key() - startOfCutRegion);
     768        }
     769    }
     770    if (withinCut)
     771        subtraction += (absPosition - startOfCutRegion);
     772    return absPosition - subtraction;
     773}
     774
     775uint64_t DeleteMap::TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap,
     776                                              uint64_t relPosition)
     777{
     778    uint64_t addition = 0;
     779    uint64_t startOfCutRegion = 0;
     780    frm_dir_map_t::const_iterator i;
     781    bool withinCut = false;
     782    bool first = true;
     783    for (i = deleteMap.constBegin(); i != deleteMap.constEnd(); i++)
     784    {
     785        if (first)
     786            withinCut = (i.value() == MARK_CUT_END);
     787        first = false;
     788        if (i.value() == MARK_CUT_START && !withinCut)
     789        {
     790            withinCut = true;
     791            startOfCutRegion = i.key();
     792            if (relPosition + addition <= startOfCutRegion)
     793                break;
     794        }
     795        else if (i.value() == MARK_CUT_END && withinCut)
     796        {
     797            withinCut = false;
     798            addition += (i.key() - startOfCutRegion);
     799        }
     800    }
     801    return relPosition + addition;
     802}
  • mythtv/libs/libmythtv/deletemap.h

    diff --git a/mythtv/libs/libmythtv/deletemap.h b/mythtv/libs/libmythtv/deletemap.h
    index e6a599b..5c4c2d5 100644
    a b class DeleteMap 
    4646    bool     IsTemporaryMark(uint64_t frame);
    4747    bool     HasTemporaryMark(void);
    4848    uint64_t GetLastFrame(uint64_t total);
     49    uint64_t TranslatePositionAbsToRel(uint64_t absPosition) {
     50        return TranslatePositionAbsToRel(m_deleteMap, absPosition);
     51    }
     52    uint64_t TranslatePositionRelToAbs(uint64_t relPosition) {
     53        return TranslatePositionRelToAbs(m_deleteMap, relPosition);
     54    }
     55    static uint64_t TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap,
     56                                              uint64_t absPosition);
     57    static uint64_t TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap,
     58                                              uint64_t relPosition);
    4959
    5060    void TrackerReset(uint64_t frame, uint64_t total);
    5161    bool TrackerWantsToJump(uint64_t frame, uint64_t total, uint64_t &to);
  • mythtv/libs/libmythtv/mythdvdplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythdvdplayer.cpp b/mythtv/libs/libmythtv/mythdvdplayer.cpp
    index 49e08af..8c8724f 100644
    a b void MythDVDPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    437437    // DVD playing non-functional under windows for now
    438438    secsplayed = 0.0f;
    439439#endif
    440     calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive);
     440        calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, false);
     441        calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, true);
    441442}
    442443
    443444void MythDVDPlayer::SeekForScreenGrab(uint64_t &number, uint64_t frameNum,
  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 1705794..53d7681 100644
    a b void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    42514251    info.values.insert("progbefore", 0);
    42524252    info.values.insert("progafter",  0);
    42534253
    4254     int playbackLen = (totalDuration > 0) ? totalDuration : totalLength;
     4254    int rawPlaybackLen = (totalDuration > 0) ? totalDuration : totalLength;
     4255    // XXX- Note that the translated playbackLen uses the frame count
     4256    // with respect to a fixed frame rate, rather than the ffmpeg
     4257    // display timecode.
     4258    int playbackLen = deleteMap.TranslatePositionAbsToRel(totalLength * video_frame_rate) / video_frame_rate;
    42554259       
    42564260    if (livetv && player_ctx->tvchain)
    42574261    {
    void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    42694273        islive = true;
    42704274    }
    42714275
    4272     float secsplayed = (float)(disp_timecode / 1000.f);
    4273     calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive);
     4276    // XXX- Note that the translated secsplayed uses the frame number
     4277    // with respect to a fixed frame rate, rather than the ffmpeg
     4278    // display timecode.
     4279    float secsplayed = ((float)deleteMap.TranslatePositionAbsToRel(framesPlayed) / video_frame_rate);
     4280    calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, false);
     4281    float rawSecsplayed = (float)(disp_timecode / 1000.f);
     4282    calcSliderPosPriv(info, paddedFields, rawPlaybackLen, rawSecsplayed, islive, true);
    42744283}
    42754284
    42764285void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields,
    42774286                                   int playbackLen, float secsplayed,
    4278                                    bool islive)
     4287                                   bool islive, bool isRaw)
    42794288{
     4289    QString rawPrefix = isRaw ? "raw" : "";
    42804290    playbackLen = max(playbackLen, 1);
    42814291    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    42824292
    4283     info.values["position"] = (int)(1000.0f * (secsplayed / (float)playbackLen));
     4293    info.values[rawPrefix + "position"] =
     4294        (int)(1000.0f * (secsplayed / (float)playbackLen));
    42844295
    42854296    int phours = (int)secsplayed / 3600;
    42864297    int pmins = ((int)secsplayed - phours * 3600) / 60;
    void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields, 
    43294340        }
    43304341    }
    43314342
    4332     info.text["description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
    4333     info.text["playedtime"] = text1;
    4334     info.text["totaltime"] = text2;
    4335     info.text["remainingtime"] = islive ? QString() : text3;
    4336     info.text["behindtime"] = islive ? text3 : QString();
     4343    info.text[rawPrefix + "description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
     4344    info.text[rawPrefix + "playedtime"] = text1;
     4345    info.text[rawPrefix + "totaltime"] = text2;
     4346    info.text[rawPrefix + "remainingtime"] = islive ? QString() : text3;
     4347    info.text[rawPrefix + "behindtime"] = islive ? text3 : QString();
    43374348}
    43384349
    43394350int MythPlayer::GetNumChapters()
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 3229f4a..eee9809 100644
    a b class MPUBLIC MythPlayer 
    344344    virtual long long CalcMaxFFTime(long long ff, bool setjump = true) const;
    345345    long long CalcRWTime(long long rw) const;
    346346    virtual void calcSliderPos(osdInfo &info, bool paddedFields = false);
     347    uint64_t TranslatePositionAbsToRel(uint64_t absPosition) {
     348        return deleteMap.TranslatePositionAbsToRel(absPosition);
     349    }
     350    uint64_t TranslatePositionRelToAbs(uint64_t relPosition) {
     351        return deleteMap.TranslatePositionRelToAbs(relPosition);
     352    }
    347353
    348354    // Commercial stuff
    349355    void SetAutoCommercialSkip(CommSkipMode autoskip)
    class MPUBLIC MythPlayer 
    521527    void  JumpToProgram(void);
    522528
    523529    void calcSliderPosPriv(osdInfo &info, bool paddedFields,
    524                            int playbackLen, float secsplayed, bool islive);
     530                           int playbackLen, float secsplayed, bool islive,
     531                           bool isRaw);
    525532
    526533  protected:
    527534    DecoderBase   *decoder;
  • mythtv/libs/libmythtv/osd.cpp

    diff --git a/mythtv/libs/libmythtv/osd.cpp b/mythtv/libs/libmythtv/osd.cpp
    index 67f7869..d60baee 100644
    a b void OSD::SetValues(const QString &window, QHash<QString,int> &map, 
    335335            found = true;
    336336        }
    337337    }
     338    if (map.contains("rawposition"))
     339    {
     340        MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *> (win->GetChild("rawposition"));
     341        if (bar)
     342        {
     343            bar->SetVisible(true);
     344            bar->SetStart(0);
     345            bar->SetTotal(1000);
     346            bar->SetUsed(map.value("rawposition"));
     347            found = true;
     348        }
     349    }
    338350
    339351    if (found)
    340352        SetExpiry(window, timeout);
  • mythtv/libs/libmythtv/tv_play.cpp

    diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
    index 1fb0b38..a8824ab 100644
    a b void TV::InitKeys(void) 
    539539            "Pause"), "P");
    540540    REG_KEY("TV Playback", "SEEKFFWD", QT_TRANSLATE_NOOP("MythControls",
    541541            "Fast Forward"), "Right");
     542    REG_KEY("TV Playback", "SEEKFFWDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     543            "Fast Forward ignoring cutlist"), "");
    542544    REG_KEY("TV Playback", "SEEKRWND", QT_TRANSLATE_NOOP("MythControls",
    543545            "Rewind"), "Left");
     546    REG_KEY("TV Playback", "SEEKRWNDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     547            "Rewind ignoring cutlist"), "");
    544548    REG_KEY("TV Playback", "ARBSEEK", QT_TRANSLATE_NOOP("MythControls",
    545549            "Arbitrary Seek"), "*");
     550    REG_KEY("TV Playback", "ARBSEEKNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     551            "Arbitrary Seek ignoring cutlist"), "");
    546552    REG_KEY("TV Playback", "CHANNELUP", QT_TRANSLATE_NOOP("MythControls",
    547553            "Channel up"), "Up");
    548554    REG_KEY("TV Playback", "CHANNELDOWN", QT_TRANSLATE_NOOP("MythControls",
    void TV::InitKeys(void) 
    553559            "Switch to the previous channel"), "H");
    554560    REG_KEY("TV Playback", "JUMPFFWD", QT_TRANSLATE_NOOP("MythControls",
    555561            "Jump ahead"), "PgDown");
     562    REG_KEY("TV Playback", "JUMPFFWDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     563            "Jump ahead ignoring cutlist"), "");
    556564    REG_KEY("TV Playback", "JUMPRWND", QT_TRANSLATE_NOOP("MythControls",
    557565            "Jump back"), "PgUp");
     566    REG_KEY("TV Playback", "JUMPRWNDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     567            "Jump back ignoring cutlist"), "");
     568    REG_KEY("TV Playback", "INFONOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     569            "Info ignoring cutlist"), "");
    558570    REG_KEY("TV Playback", "JUMPBKMRK", QT_TRANSLATE_NOOP("MythControls",
    559571            "Jump to bookmark"), "K");
    560572    REG_KEY("TV Playback", "FFWDSTICKY", QT_TRANSLATE_NOOP("MythControls",
    bool TV::DiscMenuHandleAction(PlayerContext *ctx, const QStringList &actions) 
    39413953            dvdrb->MoveButtonDown();
    39423954        }
    39433955        else if (has_action("LEFT", actions) ||
    3944                  has_action("SEEKRWND", actions))
     3956                 has_action("SEEKRWND", actions) ||
     3957                 has_action("SEEKRWNDNOCUTLIST", actions))
    39453958        {
    39463959            dvdrb->MoveButtonLeft();
    39473960        }
    39483961        else if (has_action("RIGHT", actions) ||
    3949                  has_action("SEEKFFWD", actions))
     3962                 has_action("SEEKFFWD", actions) ||
     3963                 has_action("SEEKFFWDNOCUTLIST", actions))
    39503964        {
    39513965            dvdrb->MoveButtonRight();
    39523966        }
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    41364150            }
    41374151        }
    41384152    }
    4139     else if (has_action("JUMPRWND", actions))
     4153    else if (has_action("JUMPRWND", actions) ||
     4154             has_action("JUMPRWNDNOCUTLIST", actions))
    41404155    {
    41414156        if (isDVD)
    41424157            DVDJumpBack(ctx);
    41434158        else if (GetNumChapters(ctx) > 0)
    41444159            DoJumpChapter(ctx, -1);
    41454160        else
    4146             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     4161            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"),
     4162                   true, has_action("JUMPRWND", actions));
    41474163    }
    4148     else if (has_action("JUMPFFWD", actions))
     4164    else if (has_action("JUMPFFWD", actions) ||
     4165             has_action("JUMPFFWDNOCUTLIST", actions))
    41494166    {
    41504167        if (isDVD)
    41514168            DVDJumpForward(ctx);
    41524169        else if (GetNumChapters(ctx) > 0)
    41534170            DoJumpChapter(ctx, 9999);
    41544171        else
    4155             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     4172            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"),
     4173                   true, has_action("JUMPFFWD", actions));
    41564174    }
    41574175    else if (has_action("JUMPBKMRK", actions))
    41584176    {
    41594177        ctx->LockDeletePlayer(__FILE__, __LINE__);
    4160         long long bookmark = ctx->player->GetBookmark();
    4161         long long curloc   = ctx->player->GetFramesPlayed();
     4178        uint64_t bookmark  = ctx->player->GetBookmark();
    41624179        float     rate     = ctx->player->GetFrameRate();
    4163         long long seekloc = (long long) ((bookmark - curloc) / rate);
     4180        float seekloc = ctx->player->TranslatePositionAbsToRel(bookmark) / rate;
    41644181        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    41654182
    41664183        if (bookmark > rate)
    4167             DoSeek(ctx, seekloc, tr("Jump to Bookmark"));
     4184            DoSeek(ctx, seekloc, tr("Jump to Bookmark"), false);
    41684185    }
    41694186    else if (has_action("JUMPSTART",actions))
    41704187    {
    4171         long long seekloc = +1;
    4172         ctx->LockDeletePlayer(__FILE__, __LINE__);
    4173         seekloc = (int64_t) (-1.0 * ctx->player->GetFramesPlayed() /
    4174                              ctx->player->GetFrameRate());
    4175         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    4176 
    4177         if (seekloc <= 0)
    4178             DoSeek(ctx, seekloc, tr("Jump to Beginning"));
     4188        DoSeek(ctx, 0, tr("Jump to Beginning"), false);
    41794189    }
    41804190    else if (has_action("CLEAROSD", actions))
    41814191    {
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    43224332        ChangeTimeStretch(ctx, -1);
    43234333    else if (has_action("MENU", actions))
    43244334        ShowOSDMenu(ctx);
    4325     else if (has_action("INFO", actions))
     4335    else if (has_action("INFO", actions) || has_action("INFONOCUTLIST", actions))
    43264336    {
    43274337        if (HasQueuedInput())
    43284338        {
    4329             DoArbSeek(ctx, ARBSEEK_SET);
     4339            DoArbSeek(ctx, ARBSEEK_SET, !has_action("INFONOCUTLIST", actions));
    43304340        }
    43314341        else
    43324342            ToggleOSD(ctx, true);
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, 
    45254535        else if (GetNumChapters(ctx) > 0)
    45264536            DoJumpChapter(ctx, -1);
    45274537        else
    4528             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     4538            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    45294539    }
    45304540    else if (has_action("CHANNELDOWN", actions))
    45314541    {
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, 
    45414551        else if (GetNumChapters(ctx) > 0)
    45424552            DoJumpChapter(ctx, 9999);
    45434553        else
    4544             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     4554            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    45454555    }
    45464556    else if (has_action("DELETE", actions) && !islivetv)
    45474557    {
    void TV::ProcessNetworkControlCommand(PlayerContext *ctx, 
    47664776        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    47674777
    47684778        if (tokens[2] == "BEGINNING")
    4769             DoSeek(ctx, -fplay, tr("Jump to Beginning"));
    4770         else if (tokens[2] == "FORWARD")
    4771             DoSeek(ctx, ctx->fftime, tr("Skip Ahead"));
    4772         else if (tokens[2] == "BACKWARD")
    4773             DoSeek(ctx, -ctx->rewtime, tr("Skip Back"));
    4774         else if ((tokens[2] == "POSITION") && (tokens.size() == 4) &&
     4779            DoSeek(ctx, 0, tr("Jump to Beginning"), false);
     4780        else if (tokens[2] == "FORWARD" || tokens[2] == "FORWARDNOCUTLIST")
     4781            DoSeek(ctx, ctx->fftime, tr("Skip Ahead"), true, tokens[2] == "FORWARD");
     4782        else if (tokens[2] == "BACKWARD" || tokens[2] == "BACKWARDNOCUTLIST")
     4783            DoSeek(ctx, -ctx->rewtime, tr("Skip Back"), true, tokens[2] == "BACKWARD");
     4784        else if ((tokens[2] == "POSITION" ||
     4785                  tokens[2] == "POSITIONNOCUTLIST") &&
     4786                 (tokens.size() == 4) &&
    47754787                 (tokens[3].contains(QRegExp("^\\d+$"))))
    47764788        {
    47774789            long long rel_frame = tokens[3].toInt();
    4778             rel_frame -= (long long) (fplay * (1.0 /
    4779                                       ctx->player->GetFrameRate()));
    4780             DoSeek(ctx, rel_frame, tr("Jump To"));
     4790            DoSeek(ctx, rel_frame / ctx->player->GetFrameRate(), tr("Jump To"),
     4791                   false, tokens[2] == "POSITION");
    47814792        }
    47824793    }
    47834794    else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    57965807                          const bool isDVD)
    57975808{
    57985809    const int kRewind = 4, kForward = 8, kSticky = 16, kSlippery = 32,
    5799               kRelative = 64, kAbsolute = 128, kWhenceMask = 3;
     5810              kRelative = 64, kAbsolute = 128, kIgnoreCutlist = 256,
     5811              kWhenceMask = 3;
    58005812    int flags = 0;
    58015813    if (has_action("SEEKFFWD", actions))
    58025814        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
     5815    else if (has_action("SEEKFFWDNOCUTLIST", actions))
     5816        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative | kIgnoreCutlist;
    58035817    else if (has_action("FFWDSTICKY", actions))
    58045818        flags = ARBSEEK_END     | kForward | kSticky   | kAbsolute;
    58055819    else if (has_action("RIGHT", actions))
    58065820        flags = ARBSEEK_FORWARD | kForward | kSticky   | kRelative;
    58075821    else if (has_action("SEEKRWND", actions))
    58085822        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative;
     5823    else if (has_action("SEEKRWNDNOCUTLIST", actions))
     5824        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative | kIgnoreCutlist;
    58095825    else if (has_action("RWNDSTICKY", actions))
    58105826        flags = ARBSEEK_SET     | kRewind  | kSticky   | kAbsolute;
    58115827    else if (has_action("LEFT", actions))
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58165832    int direction = (flags & kRewind) ? -1 : 1;
    58175833    if (HasQueuedInput())
    58185834    {
    5819         DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask));
     5835        DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask),
     5836                  !(flags & kIgnoreCutlist));
    58205837    }
    58215838    else if (actx->paused)
    58225839    {
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58325849                             direction * (1.001 / rate);
    58335850            QString message = (flags & kRewind) ? QString(tr("Rewind")) :
    58345851                                                 QString(tr("Forward"));
    5835             DoSeek(actx, time, message);
     5852            DoSeek(actx, time, message, true, !(flags & kIgnoreCutlist));
    58365853        }
    58375854    }
    58385855    else if (flags & kSticky)
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58435860    {
    58445861            if (smartForward)
    58455862                doSmartForward = true;
    5846             DoSeek(actx, -actx->rewtime, tr("Skip Back"));
     5863            DoSeek(actx, -actx->rewtime, tr("Skip Back"),
     5864                   true, !(flags & kIgnoreCutlist));
    58475865    }
    58485866    else
    58495867    {
    58505868        if (smartForward & doSmartForward)
    5851             DoSeek(actx, actx->rewtime, tr("Skip Ahead"));
     5869            DoSeek(actx, actx->rewtime, tr("Skip Ahead"),
     5870                   true, !(flags & kIgnoreCutlist));
    58525871        else
    5853             DoSeek(actx, actx->fftime, tr("Skip Ahead"));
     5872            DoSeek(actx, actx->fftime, tr("Skip Ahead"),
     5873                   true, !(flags & kIgnoreCutlist));
    58545874    }
    58555875    return true;
    58565876}
    58575877
    5858 void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg)
     5878void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg,
     5879                bool timeIsOffset, bool honorCutlist)
    58595880{
    58605881    bool limitkeys = false;
    58615882
    void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg) 
    58695890        keyRepeatTimer.start();
    58705891        NormalSpeed(ctx);
    58715892        time += StopFFRew(ctx);
     5893        float framerate = ctx->player->GetFrameRate();
     5894        uint64_t currentFrameAbs = ctx->player->GetFramesPlayed();
     5895        uint64_t currentFrameRel = honorCutlist ?
     5896            ctx->player->TranslatePositionAbsToRel(currentFrameAbs) :
     5897            currentFrameAbs;
     5898        int64_t desiredFrameRel = (timeIsOffset ? currentFrameRel : 0) +
     5899            time * framerate + 0.5;
     5900        if (desiredFrameRel < 0)
     5901            desiredFrameRel = 0;
     5902        uint64_t desiredFrameAbs = honorCutlist ?
     5903            ctx->player->TranslatePositionRelToAbs(desiredFrameRel) :
     5904            desiredFrameRel;
     5905        time = ((int64_t)desiredFrameAbs - (int64_t)currentFrameAbs) / framerate;
    58725906        DoPlayerSeek(ctx, time);
    58735907        UpdateOSDSeekMessage(ctx, mesg, kOSDTimeout_Med);
    58745908    }
    58755909}
    58765910
    5877 void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence)
     5911void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence, bool honorCutlist)
    58785912{
    58795913    bool ok = false;
    58805914    int seek = GetQueuedInputAsInt(&ok);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    58855919    float time = ((seek / 100) * 3600) + ((seek % 100) * 60);
    58865920
    58875921    if (whence == ARBSEEK_FORWARD)
    5888         DoSeek(ctx, time, tr("Jump Ahead"));
     5922        DoSeek(ctx, time, tr("Jump Ahead"), true, honorCutlist);
    58895923    else if (whence == ARBSEEK_REWIND)
    5890         DoSeek(ctx, -time, tr("Jump Back"));
     5924        DoSeek(ctx, -time, tr("Jump Back"), true, honorCutlist);
    58915925    else
    58925926    {
    58935927        ctx->LockDeletePlayer(__FILE__, __LINE__);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    58995933        if (whence == ARBSEEK_END)
    59005934            time = (ctx->player->CalcMaxFFTime(LONG_MAX, false) /
    59015935                    ctx->player->GetFrameRate()) - time;
    5902         else
    5903             time = time - (ctx->player->GetFramesPlayed() - 1) /
    5904                     ctx->player->GetFrameRate();
    59055936        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5906         DoSeek(ctx, time, tr("Jump To"));
     5937        DoSeek(ctx, time, tr("Jump To"), (whence != ARBSEEK_SET), honorCutlist);
    59075938    }
    59085939}
    59095940
    bool TV::CommitQueuedInput(PlayerContext *ctx) 
    68386869    {
    68396870        commited = true;
    68406871        if (HasQueuedInput())
     6872            // XXX Should the cutlist be honored?
    68416873            DoArbSeek(ctx, ARBSEEK_FORWARD);
    68426874    }
    68436875    else if (StateIsLiveTV(GetState(ctx)))
    void TV::DVDJumpBack(PlayerContext *ctx) 
    1142511457        uint chapterLength = dvdrb->GetChapterLength();
    1142611458        if ((titleLength == chapterLength) && chapterLength > 300)
    1142711459        {
    11428             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     11460            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    1142911461        }
    1143011462        else
    1143111463        {
    void TV::DVDJumpForward(PlayerContext *ctx) 
    1147311505             (currentTime < (chapterLength - (ctx->jumptime * 60))) &&
    1147411506             chapterLength > 300)
    1147511507        {
    11476             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     11508            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    1147711509        }
    1147811510        else
    1147911511        {
  • mythtv/libs/libmythtv/tv_play.h

    diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
    index 9207280..783d22c 100644
    a b class MPUBLIC TV : public QObject 
    411411
    412412    bool SeekHandleAction(PlayerContext *actx, const QStringList &actions,
    413413                          const bool isDVD);
    414     void DoSeek(PlayerContext*, float time, const QString &mesg);
     414    void DoSeek(PlayerContext*, float time, const QString &mesg,
     415                bool timeIsOffset, bool honorCutlist=true);
    415416    bool DoPlayerSeek(PlayerContext*, float time);
    416417    enum ArbSeekWhence {
    417418        ARBSEEK_SET = 0,
    class MPUBLIC TV : public QObject 
    419420        ARBSEEK_FORWARD,
    420421        ARBSEEK_END
    421422    };
    422     void DoArbSeek(PlayerContext*, ArbSeekWhence whence);
     423    void DoArbSeek(PlayerContext*, ArbSeekWhence whence, bool honorCutlist=true);
    423424    void NormalSpeed(PlayerContext*);
    424425    void ChangeSpeed(PlayerContext*, int direction);
    425426    void ToggleTimeStretch(PlayerContext*);
  • mythtv/themes/default-wide/osd.xml

    diff --git a/mythtv/themes/default-wide/osd.xml b/mythtv/themes/default-wide/osd.xml
    index 6f8f4f5..ce378bc 100644
    a b  
    352352            <area>770,10,300,30</area>
    353353            <align>right,top</align>
    354354        </textarea>
    355         <textarea name="timedisplay" from="title">
     355        <textarea name="fulltimedisplay" from="title">
    356356            <area>10,50,1060,30</area>
    357357            <align>hcenter,bottom</align>
    358358        </textarea>