Ticket #8631: seek_honors_cutlist_v8.patch

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

    diff --git a/mythtv/libs/libmythtv/bdringbuffer.cpp b/mythtv/libs/libmythtv/bdringbuffer.cpp
    index 74c615c..09d2064 100644
    a b bool BDRingBuffer::HandleAction(const QStringList &actions, int64_t pts) 
    198198        PressButton(BD_VK_DOWN, pts);
    199199    }
    200200    else if (actions.contains(ACTION_LEFT) ||
     201             actions.contains(ACTION_SEEKRWNDNOCUTLIST) ||
    201202             actions.contains(ACTION_SEEKRWND))
    202203    {
    203204        PressButton(BD_VK_LEFT, pts);
    204205    }
    205206    else if (actions.contains(ACTION_RIGHT) ||
     207             actions.contains(ACTION_SEEKFFWDNOCUTLIST) ||
    206208             actions.contains(ACTION_SEEKFFWD))
    207209    {
    208210        PressButton(BD_VK_RIGHT, pts);
  • mythtv/libs/libmythtv/deletemap.cpp

    diff --git a/mythtv/libs/libmythtv/deletemap.cpp b/mythtv/libs/libmythtv/deletemap.cpp
    index ec934a6..1b177f2 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/dvdringbuffer.cpp

    diff --git a/mythtv/libs/libmythtv/dvdringbuffer.cpp b/mythtv/libs/libmythtv/dvdringbuffer.cpp
    index 9647917..97c14e2 100644
    a b bool DVDRingBuffer::HandleAction(const QStringList &actions, int64_t pts) 
    976976        MoveButtonDown();
    977977    }
    978978    else if (actions.contains(ACTION_LEFT) ||
     979             actions.contains(ACTION_SEEKRWNDNOCUTLIST) ||
    979980             actions.contains(ACTION_SEEKRWND))
    980981    {
    981982        MoveButtonLeft();
    982983    }
    983984    else if (actions.contains(ACTION_RIGHT) ||
     985             actions.contains(ACTION_SEEKFFWDNOCUTLIST) ||
    984986             actions.contains(ACTION_SEEKFFWD))
    985987    {
    986988        MoveButtonRight();
  • mythtv/libs/libmythtv/mythdvdplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythdvdplayer.cpp b/mythtv/libs/libmythtv/mythdvdplayer.cpp
    index 42c3e7f..fa64f65 100644
    a b void MythDVDPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    426426    // DVD playing non-functional under windows for now
    427427    secsplayed = 0.0f;
    428428#endif
    429     calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive);
     429        calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, false);
     430        calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, true);
    430431}
    431432
    432433void 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 1a83c92..52aed3c 100644
    a b void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    43094309    info.values.insert("progbefore", 0);
    43104310    info.values.insert("progafter",  0);
    43114311
    4312     int playbackLen = totalDuration;
    4313 
    4314     if (totalDuration == 0 || noVideoTracks || decoder->GetCodecDecoderName() == "nuppel")
    4315         playbackLen = totalLength;
     4312    int rawPlaybackLen = totalDuration;
     4313
     4314    if (totalDuration == 0 || noVideoTracks || decoder->GetCodecDecoderName() == "nuppel")
     4315        rawPlaybackLen = totalLength;
     4316    // XXX- Note that the translated playbackLen uses the frame count
     4317    // with respect to a fixed frame rate, rather than the ffmpeg
     4318    // display timecode.
     4319    int playbackLen = deleteMap.TranslatePositionAbsToRel(totalLength * video_frame_rate) / video_frame_rate;
    43164320
    43174321    if (livetv && player_ctx->tvchain)
    43184322    {
    void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    43274331        islive = true;
    43284332    }
    43294333
    4330     float secsplayed = decoder->isCodecMPEG() ?
    4331         (float)(disp_timecode / 1000.f) :
    4332         (float)(framesPlayed / video_frame_rate);
    4333 
    4334     calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive);
     4334    // XXX- Note that the translated secsplayed uses the frame number
     4335    // with respect to a fixed frame rate, rather than the ffmpeg
     4336    // display timecode.
     4337    float secsplayed = ((float)deleteMap.TranslatePositionAbsToRel(framesPlayed) / video_frame_rate);
     4338    calcSliderPosPriv(info, paddedFields, playbackLen, secsplayed, islive, false);
     4339    float rawSecsplayed = decoder->isCodecMPEG() ?
     4340        (float)(disp_timecode / 1000.f) :
     4341        (float)(framesPlayed / video_frame_rate);
     4342    calcSliderPosPriv(info, paddedFields, rawPlaybackLen, rawSecsplayed, islive, true);
    43354343}
    43364344
    43374345void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields,
    43384346                                   int playbackLen, float secsplayed,
    4339                                    bool islive)
     4347                                   bool islive, bool isRaw)
    43404348{
     4349    QString rawPrefix = isRaw ? "raw" : "";
    43414350    playbackLen = max(playbackLen, 1);
    43424351    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    43434352
    4344     info.values["position"] = (int)(1000.0f * (secsplayed / (float)playbackLen));
     4353    info.values[rawPrefix + "position"] =
     4354        (int)(1000.0f * (secsplayed / (float)playbackLen));
    43454355
    43464356    int phours = (int)secsplayed / 3600;
    43474357    int pmins = ((int)secsplayed - phours * 3600) / 60;
    void MythPlayer::calcSliderPosPriv(osdInfo &info, bool paddedFields, 
    43874398        }
    43884399    }
    43894400
    4390     info.text["description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
    4391     info.text["playedtime"] = text1;
    4392     info.text["totaltime"] = text2;
    4393     info.text["remainingtime"] = islive ? QString() : text3;
    4394     info.text["behindtime"] = islive ? text3 : QString();
     4401    info.text[rawPrefix + "description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
     4402    info.text[rawPrefix + "playedtime"] = text1;
     4403    info.text[rawPrefix + "totaltime"] = text2;
     4404    info.text[rawPrefix + "remainingtime"] = islive ? QString() : text3;
     4405    info.text[rawPrefix + "behindtime"] = islive ? text3 : QString();
    43954406}
    43964407
    43974408int MythPlayer::GetNumChapters()
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index cdbf3d5..c6d8a12 100644
    a b class MPUBLIC MythPlayer 
    330330    virtual long long CalcMaxFFTime(long long ff, bool setjump = true) const;
    331331    long long CalcRWTime(long long rw) const;
    332332    virtual void calcSliderPos(osdInfo &info, bool paddedFields = false);
     333    uint64_t TranslatePositionAbsToRel(uint64_t absPosition) {
     334        return deleteMap.TranslatePositionAbsToRel(absPosition);
     335    }
     336    uint64_t TranslatePositionRelToAbs(uint64_t relPosition) {
     337        return deleteMap.TranslatePositionRelToAbs(relPosition);
     338    }
    333339
    334340    // Commercial stuff
    335341    void SetAutoCommercialSkip(CommSkipMode autoskip)
    class MPUBLIC MythPlayer 
    509515    void  JumpToProgram(void);
    510516
    511517    void calcSliderPosPriv(osdInfo &info, bool paddedFields,
    512                            int playbackLen, float secsplayed, bool islive);
     518                           int playbackLen, float secsplayed, bool islive,
     519                           bool isRaw);
    513520
    514521  protected:
    515522    DecoderBase   *decoder;
  • mythtv/libs/libmythtv/osd.cpp

    diff --git a/mythtv/libs/libmythtv/osd.cpp b/mythtv/libs/libmythtv/osd.cpp
    index 6e31132..eea0e84 100644
    a b void OSD::SetValues(const QString &window, QHash<QString,int> &map, 
    339339            found = true;
    340340        }
    341341    }
     342    if (map.contains("rawposition"))
     343    {
     344        MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *> (win->GetChild("rawposition"));
     345        if (bar)
     346        {
     347            bar->SetVisible(true);
     348            bar->SetStart(0);
     349            bar->SetTotal(1000);
     350            bar->SetUsed(map.value("rawposition"));
     351            found = true;
     352        }
     353    }
    342354
    343355    if (found)
    344356        SetExpiry(window, timeout);
  • mythtv/libs/libmythtv/tv.h

    diff --git a/mythtv/libs/libmythtv/tv.h b/mythtv/libs/libmythtv/tv.h
    index 59ea58a..c1de595 100644
    a b  
    2828#define ACTION_CHANNELDOWN "CHANNELDOWN"
    2929#define ACTION_SEEKRWND    "SEEKRWND"
    3030#define ACTION_SEEKFFWD    "SEEKFFWD"
     31#define ACTION_SEEKRWNDNOCUTLIST "SEEKRWNDNOCUTLIST"
     32#define ACTION_SEEKFFWDNOCUTLIST "SEEKFFWDNOCUTLIST"
    3133
    3234#define ACTION_TOGGLESTUDIOLEVELS "TOGGLESTUDIOLEVELS"
    3335#define ACTION_TOGGLEUPMIX        "TOGGLEUPMIX"
  • mythtv/libs/libmythtv/tv_play.cpp

    diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
    index 92bf948..7328ace 100644
    a b void TV::InitKeys(void) 
    489489            "Pause"), "P");
    490490    REG_KEY("TV Playback", ACTION_SEEKFFWD, QT_TRANSLATE_NOOP("MythControls",
    491491            "Fast Forward"), "Right");
     492    REG_KEY("TV Playback", ACTION_SEEKFFWDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     493            "Fast Forward ignoring cutlist"), "");
    492494    REG_KEY("TV Playback", ACTION_SEEKRWND, QT_TRANSLATE_NOOP("MythControls",
    493495            "Rewind"), "Left");
     496    REG_KEY("TV Playback", ACTION_SEEKRWNDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     497            "Rewind ignoring cutlist"), "");
    494498    REG_KEY("TV Playback", "ARBSEEK", QT_TRANSLATE_NOOP("MythControls",
    495499            "Arbitrary Seek"), "*");
     500    REG_KEY("TV Playback", "ARBSEEKNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     501            "Arbitrary Seek ignoring cutlist"), "");
    496502    REG_KEY("TV Playback", ACTION_CHANNELUP, QT_TRANSLATE_NOOP("MythControls",
    497503            "Channel up"), "Up");
    498504    REG_KEY("TV Playback", ACTION_CHANNELDOWN, QT_TRANSLATE_NOOP("MythControls",
    void TV::InitKeys(void) 
    503509            "Switch to the previous channel"), "H");
    504510    REG_KEY("TV Playback", "JUMPFFWD", QT_TRANSLATE_NOOP("MythControls",
    505511            "Jump ahead"), "PgDown");
     512    REG_KEY("TV Playback", "JUMPFFWDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     513            "Jump ahead ignoring cutlist"), "");
    506514    REG_KEY("TV Playback", "JUMPRWND", QT_TRANSLATE_NOOP("MythControls",
    507515            "Jump back"), "PgUp");
     516    REG_KEY("TV Playback", "JUMPRWNDNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     517            "Jump back ignoring cutlist"), "");
     518    REG_KEY("TV Playback", "INFONOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     519            "Info ignoring cutlist"), "");
    508520    REG_KEY("TV Playback", "JUMPBKMRK", QT_TRANSLATE_NOOP("MythControls",
    509521            "Jump to bookmark"), "K");
    510522    REG_KEY("TV Playback", "FFWDSTICKY", QT_TRANSLATE_NOOP("MythControls",
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    39423954            }
    39433955        }
    39443956    }
    3945     else if (has_action("JUMPRWND", actions))
     3957    else if (has_action("JUMPRWND", actions) ||
     3958             has_action("JUMPRWNDNOCUTLIST", actions))
    39463959    {
    39473960        if (isDVD)
    39483961            DVDJumpBack(ctx);
    39493962        else if (GetNumChapters(ctx) > 0)
    39503963            DoJumpChapter(ctx, -1);
    39513964        else
    3952             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     3965            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"),
     3966                   true, has_action("JUMPRWND", actions));
    39533967    }
    3954     else if (has_action("JUMPFFWD", actions))
     3968    else if (has_action("JUMPFFWD", actions) ||
     3969             has_action("JUMPFFWDNOCUTLIST", actions))
    39553970    {
    39563971        if (isDVD)
    39573972            DVDJumpForward(ctx);
    39583973        else if (GetNumChapters(ctx) > 0)
    39593974            DoJumpChapter(ctx, 9999);
    39603975        else
    3961             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     3976            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"),
     3977                   true, has_action("JUMPFFWD", actions));
    39623978    }
    39633979    else if (has_action("JUMPBKMRK", actions))
    39643980    {
    39653981        ctx->LockDeletePlayer(__FILE__, __LINE__);
    3966         long long bookmark = ctx->player->GetBookmark();
    3967         long long curloc   = ctx->player->GetFramesPlayed();
     3982        uint64_t bookmark  = ctx->player->GetBookmark();
    39683983        float     rate     = ctx->player->GetFrameRate();
    3969         long long seekloc = (long long) ((bookmark - curloc) / rate);
     3984        float seekloc = ctx->player->TranslatePositionAbsToRel(bookmark) / rate;
    39703985        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    39713986
    39723987        if (bookmark > rate)
    3973             DoSeek(ctx, seekloc, tr("Jump to Bookmark"));
     3988            DoSeek(ctx, seekloc, tr("Jump to Bookmark"), false);
    39743989    }
    39753990    else if (has_action("JUMPSTART",actions))
    39763991    {
    3977         long long seekloc = +1;
    3978         ctx->LockDeletePlayer(__FILE__, __LINE__);
    3979         seekloc = (int64_t) (-1.0 * ctx->player->GetFramesPlayed() /
    3980                              ctx->player->GetFrameRate());
    3981         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    3982 
    3983         if (seekloc <= 0)
    3984             DoSeek(ctx, seekloc, tr("Jump to Beginning"));
     3992        DoSeek(ctx, 0, tr("Jump to Beginning"), false);
    39853993    }
    39863994    else if (has_action("CLEAROSD", actions))
    39873995    {
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    41284136        ChangeTimeStretch(ctx, -1);
    41294137    else if (has_action("MENU", actions))
    41304138        ShowOSDMenu(ctx);
    4131     else if (has_action("INFO", actions))
     4139    else if (has_action("INFO", actions) || has_action("INFONOCUTLIST", actions))
    41324140    {
    41334141        if (HasQueuedInput())
    41344142        {
    4135             DoArbSeek(ctx, ARBSEEK_SET);
     4143            DoArbSeek(ctx, ARBSEEK_SET, !has_action("INFONOCUTLIST", actions));
    41364144        }
    41374145        else
    41384146            ToggleOSD(ctx, true);
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, const QStringList &actions) 
    43334341        else if (GetNumChapters(ctx) > 0)
    43344342            DoJumpChapter(ctx, -1);
    43354343        else
    4336             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     4344            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    43374345    }
    43384346    else if (has_action(ACTION_CHANNELDOWN, actions))
    43394347    {
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, const QStringList &actions) 
    43494357        else if (GetNumChapters(ctx) > 0)
    43504358            DoJumpChapter(ctx, 9999);
    43514359        else
    4352             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     4360            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    43534361    }
    43544362    else if (has_action("DELETE", actions) && !islivetv)
    43554363    {
    void TV::ProcessNetworkControlCommand(PlayerContext *ctx, 
    45814589        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    45824590
    45834591        if (tokens[2] == "BEGINNING")
    4584             DoSeek(ctx, -fplay, tr("Jump to Beginning"));
    4585         else if (tokens[2] == "FORWARD")
    4586             DoSeek(ctx, ctx->fftime, tr("Skip Ahead"));
    4587         else if (tokens[2] == "BACKWARD")
    4588             DoSeek(ctx, -ctx->rewtime, tr("Skip Back"));
    4589         else if ((tokens[2] == "POSITION") && (tokens.size() == 4) &&
     4592            DoSeek(ctx, 0, tr("Jump to Beginning"), false);
     4593        else if (tokens[2] == "FORWARD" || tokens[2] == "FORWARDNOCUTLIST")
     4594            DoSeek(ctx, ctx->fftime, tr("Skip Ahead"), true, tokens[2] == "FORWARD");
     4595        else if (tokens[2] == "BACKWARD" || tokens[2] == "BACKWARDNOCUTLIST")
     4596            DoSeek(ctx, -ctx->rewtime, tr("Skip Back"), true, tokens[2] == "BACKWARD");
     4597        else if ((tokens[2] == "POSITION" ||
     4598                  tokens[2] == "POSITIONNOCUTLIST") &&
     4599                 (tokens.size() == 4) &&
    45904600                 (tokens[3].contains(QRegExp("^\\d+$"))))
    45914601        {
    45924602            long long rel_frame = tokens[3].toInt();
    4593             rel_frame -= (long long) (fplay * (1.0 /
    4594                                       ctx->player->GetFrameRate()));
    4595             DoSeek(ctx, rel_frame, tr("Jump To"));
     4603            DoSeek(ctx, rel_frame / ctx->player->GetFrameRate(), tr("Jump To"),
     4604                   false, tokens[2] == "POSITION");
    45964605        }
    45974606    }
    45984607    else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    56105619                          const bool isDVD)
    56115620{
    56125621    const int kRewind = 4, kForward = 8, kSticky = 16, kSlippery = 32,
    5613               kRelative = 64, kAbsolute = 128, kWhenceMask = 3;
     5622              kRelative = 64, kAbsolute = 128, kIgnoreCutlist = 256,
     5623              kWhenceMask = 3;
    56145624    int flags = 0;
    56155625    if (has_action(ACTION_SEEKFFWD, actions))
    56165626        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
     5627    else if (has_action("SEEKFFWDNOCUTLIST", actions))
     5628        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative | kIgnoreCutlist;
    56175629    else if (has_action("FFWDSTICKY", actions))
    56185630        flags = ARBSEEK_END     | kForward | kSticky   | kAbsolute;
    56195631    else if (has_action(ACTION_RIGHT, actions))
    56205632        flags = ARBSEEK_FORWARD | kForward | kSticky   | kRelative;
    56215633    else if (has_action(ACTION_SEEKRWND, actions))
    56225634        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative;
     5635    else if (has_action("SEEKRWNDNOCUTLIST", actions))
     5636        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative | kIgnoreCutlist;
    56235637    else if (has_action("RWNDSTICKY", actions))
    56245638        flags = ARBSEEK_SET     | kRewind  | kSticky   | kAbsolute;
    56255639    else if (has_action(ACTION_LEFT, actions))
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    56305644    int direction = (flags & kRewind) ? -1 : 1;
    56315645    if (HasQueuedInput())
    56325646    {
    5633         DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask));
     5647        DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask),
     5648                  !(flags & kIgnoreCutlist));
    56345649    }
    56355650    else if (actx->paused)
    56365651    {
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    56465661                             direction * (1.001 / rate);
    56475662            QString message = (flags & kRewind) ? QString(tr("Rewind")) :
    56485663                                                 QString(tr("Forward"));
    5649             DoSeek(actx, time, message);
     5664            DoSeek(actx, time, message, true, !(flags & kIgnoreCutlist));
    56505665        }
    56515666    }
    56525667    else if (flags & kSticky)
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    56575672    {
    56585673            if (smartForward)
    56595674                doSmartForward = true;
    5660             DoSeek(actx, -actx->rewtime, tr("Skip Back"));
     5675            DoSeek(actx, -actx->rewtime, tr("Skip Back"),
     5676                   true, !(flags & kIgnoreCutlist));
    56615677    }
    56625678    else
    56635679    {
    56645680        if (smartForward & doSmartForward)
    5665             DoSeek(actx, actx->rewtime, tr("Skip Ahead"));
     5681            DoSeek(actx, actx->rewtime, tr("Skip Ahead"),
     5682                   true, !(flags & kIgnoreCutlist));
    56665683        else
    5667             DoSeek(actx, actx->fftime, tr("Skip Ahead"));
     5684            DoSeek(actx, actx->fftime, tr("Skip Ahead"),
     5685                   true, !(flags & kIgnoreCutlist));
    56685686    }
    56695687    return true;
    56705688}
    56715689
    5672 void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg)
     5690void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg,
     5691                bool timeIsOffset, bool honorCutlist)
    56735692{
    56745693    bool limitkeys = false;
    56755694
    void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg) 
    56835702        keyRepeatTimer.start();
    56845703        NormalSpeed(ctx);
    56855704        time += StopFFRew(ctx);
     5705        float framerate = ctx->player->GetFrameRate();
     5706        uint64_t currentFrameAbs = ctx->player->GetFramesPlayed();
     5707        uint64_t currentFrameRel = honorCutlist ?
     5708            ctx->player->TranslatePositionAbsToRel(currentFrameAbs) :
     5709            currentFrameAbs;
     5710        int64_t desiredFrameRel = (timeIsOffset ? currentFrameRel : 0) +
     5711            time * framerate + 0.5;
     5712        if (desiredFrameRel < 0)
     5713            desiredFrameRel = 0;
     5714        uint64_t desiredFrameAbs = honorCutlist ?
     5715            ctx->player->TranslatePositionRelToAbs(desiredFrameRel) :
     5716            desiredFrameRel;
     5717        time = ((int64_t)desiredFrameAbs - (int64_t)currentFrameAbs) / framerate;
    56865718        DoPlayerSeek(ctx, time);
    56875719        UpdateOSDSeekMessage(ctx, mesg, kOSDTimeout_Med);
    56885720    }
    56895721}
    56905722
    5691 void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence)
     5723void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence, bool honorCutlist)
    56925724{
    56935725    bool ok = false;
    56945726    int seek = GetQueuedInputAsInt(&ok);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    56995731    float time = ((seek / 100) * 3600) + ((seek % 100) * 60);
    57005732
    57015733    if (whence == ARBSEEK_FORWARD)
    5702         DoSeek(ctx, time, tr("Jump Ahead"));
     5734        DoSeek(ctx, time, tr("Jump Ahead"), true, honorCutlist);
    57035735    else if (whence == ARBSEEK_REWIND)
    5704         DoSeek(ctx, -time, tr("Jump Back"));
     5736        DoSeek(ctx, -time, tr("Jump Back"), true, honorCutlist);
    57055737    else
    57065738    {
    57075739        ctx->LockDeletePlayer(__FILE__, __LINE__);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    57135745        if (whence == ARBSEEK_END)
    57145746            time = (ctx->player->CalcMaxFFTime(LONG_MAX, false) /
    57155747                    ctx->player->GetFrameRate()) - time;
    5716         else
    5717             time = time - (ctx->player->GetFramesPlayed() - 1) /
    5718                     ctx->player->GetFrameRate();
    57195748        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5720         DoSeek(ctx, time, tr("Jump To"));
     5749        DoSeek(ctx, time, tr("Jump To"), (whence != ARBSEEK_SET), honorCutlist);
    57215750    }
    57225751}
    57235752
    bool TV::CommitQueuedInput(PlayerContext *ctx) 
    66526681    {
    66536682        commited = true;
    66546683        if (HasQueuedInput())
     6684            // XXX Should the cutlist be honored?
    66556685            DoArbSeek(ctx, ARBSEEK_FORWARD);
    66566686    }
    66576687    else if (StateIsLiveTV(GetState(ctx)))
    void TV::DVDJumpBack(PlayerContext *ctx) 
    1127711307        uint chapterLength = dvdrb->GetChapterLength();
    1127811308        if ((titleLength == chapterLength) && chapterLength > 300)
    1127911309        {
    11280             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     11310            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    1128111311        }
    1128211312        else
    1128311313        {
    void TV::DVDJumpForward(PlayerContext *ctx) 
    1132511355             (currentTime < (chapterLength - (ctx->jumptime * 60))) &&
    1132611356             chapterLength > 300)
    1132711357        {
    11328             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     11358            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    1132911359        }
    1133011360        else
    1133111361        {
  • mythtv/libs/libmythtv/tv_play.h

    diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
    index 53957c2..f839d5c 100644
    a b class MPUBLIC TV : public QObject 
    401401
    402402    bool SeekHandleAction(PlayerContext *actx, const QStringList &actions,
    403403                          const bool isDVD);
    404     void DoSeek(PlayerContext*, float time, const QString &mesg);
     404    void DoSeek(PlayerContext*, float time, const QString &mesg,
     405                bool timeIsOffset, bool honorCutlist=true);
    405406    bool DoPlayerSeek(PlayerContext*, float time);
    406407    enum ArbSeekWhence {
    407408        ARBSEEK_SET = 0,
    class MPUBLIC TV : public QObject 
    409410        ARBSEEK_FORWARD,
    410411        ARBSEEK_END
    411412    };
    412     void DoArbSeek(PlayerContext*, ArbSeekWhence whence);
     413    void DoArbSeek(PlayerContext*, ArbSeekWhence whence, bool honorCutlist=true);
    413414    void NormalSpeed(PlayerContext*);
    414415    void ChangeSpeed(PlayerContext*, int direction);
    415416    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>