Ticket #8631: seek_honors_cutlist_v5.patch

File seek_honors_cutlist_v5.patch, 27.1 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 198e1fa..634ebac 100644
    a b void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    42554255    info.values.insert("progbefore", 0);
    42564256    info.values.insert("progafter",  0);
    42574257
    4258     int playbackLen = (totalDuration > 0) ? totalDuration : totalLength;
     4258    int rawPlaybackLen = (totalDuration > 0) ? totalDuration : totalLength;
     4259    // XXX- Note that the translated playbackLen uses the frame count
     4260    // with respect to a fixed frame rate, rather than the ffmpeg
     4261    // display timecode.
     4262    int playbackLen = deleteMap.TranslatePositionAbsToRel(totalLength * video_frame_rate) / video_frame_rate;
    42594263       
    42604264    if (livetv && player_ctx->tvchain)
    42614265    {
    void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    42734277        islive = true;
    42744278    }
    42754279
    4276     float secsplayed = (float)(disp_timecode / 1000.f);
    4277     calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive);
     4280    // XXX- Note that the translated secsplayed uses the frame number
     4281    // with respect to a fixed frame rate, rather than the ffmpeg
     4282    // display timecode.
     4283    float secsplayed = ((float)deleteMap.TranslatePositionAbsToRel(framesPlayed) / video_frame_rate);
     4284    calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, false);
     4285    float rawSecsplayed = (float)(disp_timecode / 1000.f);
     4286    calcSliderPosPriv(info, paddedFields, rawPlaybackLen, rawSecsplayed, islive, true);
    42784287}
    42794288
    42804289void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields,
    42814290                                   int playbackLen, float secsplayed,
    4282                                    bool islive)
     4291                                   bool islive, bool isRaw)
    42834292{
     4293    QString rawPrefix = isRaw ? "raw" : "";
    42844294    playbackLen = max(playbackLen, 1);
    42854295    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    42864296
    4287     info.values["position"] = (int)(1000.0f * (secsplayed / (float)playbackLen));
     4297    info.values[rawPrefix + "position"] =
     4298        (int)(1000.0f * (secsplayed / (float)playbackLen));
    42884299
    42894300    int phours = (int)secsplayed / 3600;
    42904301    int pmins = ((int)secsplayed - phours * 3600) / 60;
    void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields, 
    43334344        }
    43344345    }
    43354346
    4336     info.text["description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
    4337     info.text["playedtime"] = text1;
    4338     info.text["totaltime"] = text2;
    4339     info.text["remainingtime"] = islive ? QString() : text3;
    4340     info.text["behindtime"] = islive ? text3 : QString();
     4347    info.text[rawPrefix + "description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
     4348    info.text[rawPrefix + "playedtime"] = text1;
     4349    info.text[rawPrefix + "totaltime"] = text2;
     4350    info.text[rawPrefix + "remainingtime"] = islive ? QString() : text3;
     4351    info.text[rawPrefix + "behindtime"] = islive ? text3 : QString();
    43414352}
    43424353
    43434354int MythPlayer::GetNumChapters()
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index b776296..0b24ae0 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 d7a381c..583081c 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) 
    39433955            dvdrb->MoveButtonDown();
    39443956        }
    39453957        else if (has_action("LEFT", actions) ||
    3946                  has_action("SEEKRWND", actions))
     3958                 has_action("SEEKRWND", actions) ||
     3959                 has_action("SEEKRWNDNOCUTLIST", actions))
    39473960        {
    39483961            dvdrb->MoveButtonLeft();
    39493962        }
    39503963        else if (has_action("RIGHT", actions) ||
    3951                  has_action("SEEKFFWD", actions))
     3964                 has_action("SEEKFFWD", actions) ||
     3965                 has_action("SEEKFFWDNOCUTLIST", actions))
    39523966        {
    39533967            dvdrb->MoveButtonRight();
    39543968        }
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    41384152            }
    41394153        }
    41404154    }
    4141     else if (has_action("JUMPRWND", actions))
     4155    else if (has_action("JUMPRWND", actions) ||
     4156             has_action("JUMPRWNDNOCUTLIST", actions))
    41424157    {
    41434158        if (isDVD)
    41444159            DVDJumpBack(ctx);
    41454160        else if (GetNumChapters(ctx) > 0)
    41464161            DoJumpChapter(ctx, -1);
    41474162        else
    4148             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     4163            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"),
     4164                   true, has_action("JUMPRWND", actions));
    41494165    }
    4150     else if (has_action("JUMPFFWD", actions))
     4166    else if (has_action("JUMPFFWD", actions) ||
     4167             has_action("JUMPFFWDNOCUTLIST", actions))
    41514168    {
    41524169        if (isDVD)
    41534170            DVDJumpForward(ctx);
    41544171        else if (GetNumChapters(ctx) > 0)
    41554172            DoJumpChapter(ctx, 9999);
    41564173        else
    4157             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     4174            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"),
     4175                   true, has_action("JUMPFFWD", actions));
    41584176    }
    41594177    else if (has_action("JUMPBKMRK", actions))
    41604178    {
    41614179        ctx->LockDeletePlayer(__FILE__, __LINE__);
    4162         long long bookmark = ctx->player->GetBookmark();
    4163         long long curloc   = ctx->player->GetFramesPlayed();
     4180        uint64_t bookmark = ctx->player->GetBookmark();
    41644181        float mult = 1.0f;
    41654182        if (ctx->last_framerate)
    41664183            mult = 1.0f / ctx->last_framerate;
    4167         long long seekloc = (long long) ((bookmark - curloc) * mult);
     4184        float seekloc = ctx->player->TranslatePositionAbsToRel(bookmark) * mult;
    41684185        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    41694186
    41704187        if (bookmark > ctx->last_framerate)
    41714188        {
    4172             DoSeek(ctx, seekloc, tr("Jump to Bookmark"));
     4189            DoSeek(ctx, seekloc, tr("Jump to Bookmark"), false);
    41734190        }
    41744191    }
    41754192    else if (has_action("JUMPSTART",actions))
    41764193    {
    4177         long long seekloc = +1;
    4178         ctx->LockDeletePlayer(__FILE__, __LINE__);
    4179         if (ctx->player && ctx->last_framerate >= 0.0001f)
    4180         {
    4181             seekloc = (int64_t) (-1.0 * ctx->player->GetFramesPlayed() /
    4182                                  ctx->last_framerate);
    4183         }
    4184         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    4185 
    4186         if (seekloc <= 0)
    4187             DoSeek(ctx, seekloc, tr("Jump to Beginning"));
     4194        DoSeek(ctx, 0, tr("Jump to Beginning"), false);
    41884195    }
    41894196    else if (has_action("CLEAROSD", actions))
    41904197    {
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    43314338        ChangeTimeStretch(ctx, -1);
    43324339    else if (has_action("MENU", actions))
    43334340        ShowOSDMenu(ctx);
    4334     else if (has_action("INFO", actions))
     4341    else if (has_action("INFO", actions) || has_action("INFONOCUTLIST", actions))
    43354342    {
    43364343        if (HasQueuedInput())
    43374344        {
    4338             DoArbSeek(ctx, ARBSEEK_SET);
     4345            DoArbSeek(ctx, ARBSEEK_SET, !has_action("INFONOCUTLIST", actions));
    43394346        }
    43404347        else
    43414348            ToggleOSD(ctx, true);
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, 
    45344541        else if (GetNumChapters(ctx) > 0)
    45354542            DoJumpChapter(ctx, -1);
    45364543        else
    4537             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     4544            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    45384545    }
    45394546    else if (has_action("CHANNELDOWN", actions))
    45404547    {
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, 
    45504557        else if (GetNumChapters(ctx) > 0)
    45514558            DoJumpChapter(ctx, 9999);
    45524559        else
    4553             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     4560            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    45544561    }
    45554562    else if (has_action("DELETE", actions) && !islivetv)
    45564563    {
    void TV::ProcessNetworkControlCommand(PlayerContext *ctx, 
    47754782        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    47764783
    47774784        if (tokens[2] == "BEGINNING")
    4778             DoSeek(ctx, -fplay, tr("Jump to Beginning"));
    4779         else if (tokens[2] == "FORWARD")
    4780             DoSeek(ctx, ctx->fftime, tr("Skip Ahead"));
    4781         else if (tokens[2] == "BACKWARD")
    4782             DoSeek(ctx, -ctx->rewtime, tr("Skip Back"));
    4783         else if ((tokens[2] == "POSITION") && (tokens.size() == 4) &&
     4785            DoSeek(ctx, 0, tr("Jump to Beginning"), false);
     4786        else if (tokens[2] == "FORWARD" || tokens[2] == "FORWARDNOCUTLIST")
     4787            DoSeek(ctx, ctx->fftime, tr("Skip Ahead"), true, tokens[2] == "FORWARD");
     4788        else if (tokens[2] == "BACKWARD" || tokens[2] == "BACKWARDNOCUTLIST")
     4789            DoSeek(ctx, -ctx->rewtime, tr("Skip Back"), true, tokens[2] == "BACKWARD");
     4790        else if ((tokens[2] == "POSITION" ||
     4791                  tokens[2] == "POSITIONNOCUTLIST") &&
     4792                 (tokens.size() == 4) &&
    47844793                 (tokens[3].contains(QRegExp("^\\d+$"))) &&
    47854794                 ctx->last_framerate)
    47864795        {
    47874796            long long rel_frame = tokens[3].toInt();
    4788             rel_frame -= (long long) (fplay * (1.0 / ctx->last_framerate)),
    4789             DoSeek(ctx, rel_frame, tr("Jump To"));
     4797            DoSeek(ctx, rel_frame / ctx->last_framerate, tr("Jump To"),
     4798                   false, tokens[2] == "POSITION");
    47904799        }
    47914800    }
    47924801    else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58065815                          const bool isDVD)
    58075816{
    58085817    const int kRewind = 4, kForward = 8, kSticky = 16, kSlippery = 32,
    5809               kRelative = 64, kAbsolute = 128, kWhenceMask = 3;
     5818              kRelative = 64, kAbsolute = 128, kIgnoreCutlist = 256,
     5819              kWhenceMask = 3;
    58105820    int flags = 0;
    58115821    if (has_action("SEEKFFWD", actions))
    58125822        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
     5823    else if (has_action("SEEKFFWDNOCUTLIST", actions))
     5824        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative | kIgnoreCutlist;
    58135825    else if (has_action("FFWDSTICKY", actions))
    58145826        flags = ARBSEEK_END     | kForward | kSticky   | kAbsolute;
    58155827    else if (has_action("RIGHT", actions))
    58165828        flags = ARBSEEK_FORWARD | kForward | kSticky   | kRelative;
    58175829    else if (has_action("SEEKRWND", actions))
    58185830        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative;
     5831    else if (has_action("SEEKRWNDNOCUTLIST", actions))
     5832        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative | kIgnoreCutlist;
    58195833    else if (has_action("RWNDSTICKY", actions))
    58205834        flags = ARBSEEK_SET     | kRewind  | kSticky   | kAbsolute;
    58215835    else if (has_action("LEFT", actions))
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58265840    int direction = (flags & kRewind) ? -1 : 1;
    58275841    if (HasQueuedInput())
    58285842    {
    5829         DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask));
     5843        DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask),
     5844                  !(flags & kIgnoreCutlist));
    58305845    }
    58315846    else if (actx->paused)
    58325847    {
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58365851                             direction * (1.001 / actx->last_framerate);
    58375852            QString message = (flags & kRewind) ? QString(tr("Rewind")) :
    58385853                                                 QString(tr("Forward"));
    5839             DoSeek(actx, time, message);
     5854            DoSeek(actx, time, message, true, !(flags & kIgnoreCutlist));
    58405855        }
    58415856    }
    58425857    else if (flags & kSticky)
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    58475862    {
    58485863            if (smartForward)
    58495864                doSmartForward = true;
    5850             DoSeek(actx, -actx->rewtime, tr("Skip Back"));
     5865            DoSeek(actx, -actx->rewtime, tr("Skip Back"),
     5866                   true, !(flags & kIgnoreCutlist));
    58515867    }
    58525868    else
    58535869    {
    58545870        if (smartForward & doSmartForward)
    5855             DoSeek(actx, actx->rewtime, tr("Skip Ahead"));
     5871            DoSeek(actx, actx->rewtime, tr("Skip Ahead"),
     5872                   true, !(flags & kIgnoreCutlist));
    58565873        else
    5857             DoSeek(actx, actx->fftime, tr("Skip Ahead"));
     5874            DoSeek(actx, actx->fftime, tr("Skip Ahead"),
     5875                   true, !(flags & kIgnoreCutlist));
    58585876    }
    58595877    return true;
    58605878}
    58615879
    5862 void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg)
     5880void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg,
     5881                bool timeIsOffset, bool honorCutlist)
    58635882{
    58645883    bool limitkeys = false;
    58655884
    void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg) 
    58735892        keyRepeatTimer.start();
    58745893        NormalSpeed(ctx);
    58755894        time += StopFFRew(ctx);
     5895        float framerate = ctx->last_framerate;
     5896        uint64_t currentFrameAbs = ctx->player->GetFramesPlayed();
     5897        uint64_t currentFrameRel = honorCutlist ?
     5898            ctx->player->TranslatePositionAbsToRel(currentFrameAbs) :
     5899            currentFrameAbs;
     5900        int64_t desiredFrameRel = (timeIsOffset ? currentFrameRel : 0) +
     5901            time * framerate + 0.5;
     5902        if (desiredFrameRel < 0)
     5903            desiredFrameRel = 0;
     5904        uint64_t desiredFrameAbs = honorCutlist ?
     5905            ctx->player->TranslatePositionRelToAbs(desiredFrameRel) :
     5906            desiredFrameRel;
     5907        time = ((int64_t)desiredFrameAbs - (int64_t)currentFrameAbs) / framerate;
    58765908        DoPlayerSeek(ctx, time);
    58775909        UpdateOSDSeekMessage(ctx, mesg, kOSDTimeout_Med);
    58785910    }
    58795911}
    58805912
    5881 void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence)
     5913void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence, bool honorCutlist)
    58825914{
    58835915    bool ok = false;
    58845916    int seek = GetQueuedInputAsInt(&ok);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    58895921    float time = ((seek / 100) * 3600) + ((seek % 100) * 60);
    58905922
    58915923    if (whence == ARBSEEK_FORWARD)
    5892         DoSeek(ctx, time, tr("Jump Ahead"));
     5924        DoSeek(ctx, time, tr("Jump Ahead"), true, honorCutlist);
    58935925    else if (whence == ARBSEEK_REWIND)
    5894         DoSeek(ctx, -time, tr("Jump Back"));
     5926        DoSeek(ctx, -time, tr("Jump Back"), true, honorCutlist);
    58955927    else
    58965928    {
    58975929        ctx->LockDeletePlayer(__FILE__, __LINE__);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    59035935        if (whence == ARBSEEK_END)
    59045936            time = (ctx->player->CalcMaxFFTime(LONG_MAX, false) /
    59055937                    ctx->last_framerate) - time;
    5906         else
    5907             time = time - (ctx->player->GetFramesPlayed() - 1) /
    5908                     ctx->last_framerate;
    59095938        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5910         DoSeek(ctx, time, tr("Jump To"));
     5939        DoSeek(ctx, time, tr("Jump To"), (whence != ARBSEEK_SET), honorCutlist);
    59115940    }
    59125941}
    59135942
    bool TV::CommitQueuedInput(PlayerContext *ctx) 
    68456874    {
    68466875        commited = true;
    68476876        if (HasQueuedInput())
     6877            // XXX Should the cutlist be honored?
    68486878            DoArbSeek(ctx, ARBSEEK_FORWARD);
    68496879    }
    68506880    else if (StateIsLiveTV(GetState(ctx)))
    void TV::DVDJumpBack(PlayerContext *ctx) 
    1143711467        uint chapterLength = dvdrb->GetChapterLength();
    1143811468        if ((titleLength == chapterLength) && chapterLength > 300)
    1143911469        {
    11440             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     11470            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    1144111471        }
    1144211472        else
    1144311473        {
    void TV::DVDJumpForward(PlayerContext *ctx) 
    1148511515             (currentTime < (chapterLength - (ctx->jumptime * 60))) &&
    1148611516             chapterLength > 300)
    1148711517        {
    11488             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     11518            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    1148911519        }
    1149011520        else
    1149111521        {
  • 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>