Ticket #8631: seek_honors_cutlist_v12.patch

File seek_honors_cutlist_v12.patch, 28.2 KB (added by Jim Stichnoth <stichnot@…>, 9 years ago)

Fixed a long-standing bug in DeleteMap::TranslatePositionAbsToRel?().

  • mythtv/libs/libmythtv/bdringbuffer.cpp

    diff --git a/mythtv/libs/libmythtv/bdringbuffer.cpp b/mythtv/libs/libmythtv/bdringbuffer.cpp
    index 8028527..bd7fc9f 100644
    a b bool BDRingBuffer::HandleAction(const QStringList &actions, int64_t pts) 
    199199        PressButton(BD_VK_DOWN, pts);
    200200    }
    201201    else if (actions.contains(ACTION_LEFT) ||
     202             actions.contains(ACTION_SEEKRWNDNOCUTLIST) ||
    202203             actions.contains(ACTION_SEEKRWND))
    203204    {
    204205        PressButton(BD_VK_LEFT, pts);
    205206    }
    206207    else if (actions.contains(ACTION_RIGHT) ||
     208             actions.contains(ACTION_SEEKFFWDNOCUTLIST) ||
    207209             actions.contains(ACTION_SEEKFFWD))
    208210    {
    209211        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 0a1ac66..ef6d4ba 100644
    a b void DeleteMap::UpdateSeekAmount(int change, double framerate) 
    127127    }
    128128}
    129129
    130 /**
     130static QString createTimeString(uint64_t frame, uint64_t total,
     131                                double frame_rate, bool full_resolution)
     132{
     133    int secs   = (int)(frame / frame_rate);
     134    int frames = frame - (int)(secs * frame_rate);
     135    int totalSecs = (int)(total / frame_rate);
     136    QString timestr;
     137    if (totalSecs >= 3600)
     138        timestr = QString::number(secs / 3600) + ":";
     139    timestr += QString("%1").arg((secs / 60) % 60, 2, 10, QChar(48)) +
     140        QString(":%1").arg(secs % 60, 2, 10, QChar(48));
     141    if (full_resolution)
     142        timestr += QString(".%1").arg(frames, 2, 10, QChar(48));
     143    return timestr;
     144}
     145
     146 /**
    131147 * \brief Show and update the edit mode On Screen Display. The cut regions
    132148 *        are only refreshed if the deleteMap has been updated.
    133149 */
    void DeleteMap::UpdateOSD(uint64_t frame, uint64_t total, double frame_rate, 
    145161    infoMap.detach();
    146162    ctx->UnlockPlayingInfo(__FILE__, __LINE__);
    147163
    148     int secs   = (int)(frame / frame_rate);
    149     int frames = frame - (int)(secs * frame_rate);
    150     QString timestr = QString::number(secs / 3600) +
    151                       QString(":%1").arg((secs / 60) % 60, 2, 10, QChar(48)) +
    152                       QString(":%1").arg(secs % 60, 2, 10, QChar(48)) +
    153                       QString(".%1").arg(frames, 2, 10, QChar(48));
    154 
    155164    QString cutmarker = " ";
    156165    if (IsInDelete(frame))
    157166        cutmarker = QObject::tr("cut");
    158167
     168    QString timestr = createTimeString(frame, total, frame_rate, true);
     169    uint64_t relTotal = TranslatePositionAbsToRel(total);
     170    QString relTimeDisplay = createTimeString(TranslatePositionAbsToRel(frame),
     171                                              relTotal, frame_rate, false);
     172    QString relLengthDisplay = createTimeString(relTotal,
     173                                                relTotal, frame_rate, false);
    159174    infoMap["timedisplay"]  = timestr;
    160175    infoMap["framedisplay"] = QString::number(frame);
    161176    infoMap["cutindicator"] = cutmarker;
    162177    infoMap["title"]        = QObject::tr("Edit");
    163178    infoMap["seekamount"]   = m_seekText;;
     179    infoMap["reltimedisplay"] = relTimeDisplay;
     180    infoMap["rellengthdisplay"] = relLengthDisplay;
     181    infoMap["fulltimedisplay"] = timestr + " (" +
     182        QObject::tr("%1 of %2").arg(relTimeDisplay).arg(relLengthDisplay) + ")";
    164183
    165184    QHash<QString,float> posMap;
    166185    posMap.insert("position", (float)((double)frame/(double)total));
    bool DeleteMap::IsSaved(PlayerContext *ctx) 
    819838
    820839    return currentMap == savedMap;
    821840}
     841
     842uint64_t DeleteMap::TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap,
     843                                              uint64_t absPosition)
     844{
     845    uint64_t subtraction = 0;
     846    uint64_t startOfCutRegion = 0;
     847    frm_dir_map_t::const_iterator i;
     848    bool withinCut = false;
     849    bool first = true;
     850    for (i = deleteMap.constBegin(); i != deleteMap.constEnd(); ++i)
     851    {
     852        if (first)
     853            withinCut = (i.value() == MARK_CUT_END);
     854        first = false;
     855        if (i.key() > absPosition)
     856            break;
     857        if (i.value() == MARK_CUT_START && !withinCut)
     858        {
     859            withinCut = true;
     860            startOfCutRegion = i.key();
     861        }
     862        else if (i.value() == MARK_CUT_END && withinCut)
     863        {
     864            withinCut = false;
     865            subtraction += (i.key() - startOfCutRegion);
     866        }
     867    }
     868    if (withinCut)
     869        subtraction += (absPosition - startOfCutRegion);
     870    return absPosition - subtraction;
     871}
     872
     873uint64_t DeleteMap::TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap,
     874                                              uint64_t relPosition)
     875{
     876    uint64_t addition = 0;
     877    uint64_t startOfCutRegion = 0;
     878    frm_dir_map_t::const_iterator i;
     879    bool withinCut = false;
     880    bool first = true;
     881    for (i = deleteMap.constBegin(); i != deleteMap.constEnd(); ++i)
     882    {
     883        if (first)
     884            withinCut = (i.value() == MARK_CUT_END);
     885        first = false;
     886        if (i.value() == MARK_CUT_START && !withinCut)
     887        {
     888            withinCut = true;
     889            startOfCutRegion = i.key();
     890            if (relPosition + addition <= startOfCutRegion)
     891                break;
     892        }
     893        else if (i.value() == MARK_CUT_END && withinCut)
     894        {
     895            withinCut = false;
     896            addition += (i.key() - startOfCutRegion);
     897        }
     898    }
     899    return relPosition + addition;
     900}
  • mythtv/libs/libmythtv/deletemap.h

    diff --git a/mythtv/libs/libmythtv/deletemap.h b/mythtv/libs/libmythtv/deletemap.h
    index 2dfa190..ffdb2d0 100644
    a b class DeleteMap 
    5959    bool     IsTemporaryMark(uint64_t frame);
    6060    bool     HasTemporaryMark(void);
    6161    uint64_t GetLastFrame(uint64_t total);
     62    uint64_t TranslatePositionAbsToRel(uint64_t absPosition) {
     63        return TranslatePositionAbsToRel(m_deleteMap, absPosition);
     64    }
     65    uint64_t TranslatePositionRelToAbs(uint64_t relPosition) {
     66        return TranslatePositionRelToAbs(m_deleteMap, relPosition);
     67    }
     68    static uint64_t TranslatePositionAbsToRel(const frm_dir_map_t &deleteMap,
     69                                              uint64_t absPosition);
     70    static uint64_t TranslatePositionRelToAbs(const frm_dir_map_t &deleteMap,
     71                                              uint64_t relPosition);
    6272
    6373    void TrackerReset(uint64_t frame, uint64_t total);
    6474    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 318f8f8..fd20394 100644
    a b bool DVDRingBuffer::HandleAction(const QStringList &actions, int64_t pts) 
    11431143        MoveButtonDown();
    11441144    }
    11451145    else if (actions.contains(ACTION_LEFT) ||
     1146             actions.contains(ACTION_SEEKRWNDNOCUTLIST) ||
    11461147             actions.contains(ACTION_SEEKRWND))
    11471148    {
    11481149        MoveButtonLeft();
    11491150    }
    11501151    else if (actions.contains(ACTION_RIGHT) ||
     1152             actions.contains(ACTION_SEEKFFWDNOCUTLIST) ||
    11511153             actions.contains(ACTION_SEEKFFWD))
    11521154    {
    11531155        MoveButtonRight();
  • mythtv/libs/libmythtv/mythplayer.cpp

    diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
    index 4757f16..ea6b7ee 100644
    a b void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    46194619    playbackLen = max(playbackLen, 1);
    46204620    secsplayed  = min((float)playbackLen, max(secsplayed, 0.0f));
    46214621
    4622     info.values.insert("secondsplayed", (int)secsplayed);
    4623     info.values.insert("totalseconds", playbackLen);
    4624     info.values["position"] = (int)(1000.0f * (secsplayed / (float)playbackLen));
     4622    // Set the raw values, followed by the translated values.
     4623    for (int i = 0; i < 2 ; ++i)
     4624    {
     4625        QString rawPrefix = (i == 0 ? "raw" : "");
     4626        if (i > 0)
     4627        {
     4628            playbackLen = deleteMap.TranslatePositionAbsToRel(playbackLen * video_frame_rate) /
     4629                video_frame_rate;
     4630            secsplayed = deleteMap.TranslatePositionAbsToRel(secsplayed * video_frame_rate) /
     4631                video_frame_rate;
     4632        }
     4633
     4634    info.values.insert(rawPrefix + "secondsplayed", (int)secsplayed);
     4635    info.values.insert(rawPrefix + "totalseconds", playbackLen);
     4636    info.values[rawPrefix + "position"] = (int)(1000.0f * (secsplayed / (float)playbackLen));
    46254637
    46264638    int phours = (int)secsplayed / 3600;
    46274639    int pmins = ((int)secsplayed - phours * 3600) / 60;
    void MythPlayer::calcSliderPos(osdInfo &info, bool paddedFields) 
    46704682        }
    46714683    }
    46724684
    4673     info.text["description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
    4674     info.text["playedtime"] = text1;
    4675     info.text["totaltime"] = text2;
    4676     info.text["remainingtime"] = islive ? QString() : text3;
    4677     info.text["behindtime"] = islive ? text3 : QString();
     4685    info.text[rawPrefix + "description"] = QObject::tr("%1 of %2").arg(text1).arg(text2);
     4686    info.text[rawPrefix + "playedtime"] = text1;
     4687    info.text[rawPrefix + "totaltime"] = text2;
     4688    info.text[rawPrefix + "remainingtime"] = islive ? QString() : text3;
     4689    info.text[rawPrefix + "behindtime"] = islive ? text3 : QString();
     4690    }
    46784691}
    46794692
    46804693int MythPlayer::GetNumChapters()
  • mythtv/libs/libmythtv/mythplayer.h

    diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
    index 56ddc01..dd8a296 100644
    a b class MTV_PUBLIC MythPlayer 
    353353    virtual long long CalcMaxFFTime(long long ff, bool setjump = true) const;
    354354    long long CalcRWTime(long long rw) const;
    355355    virtual void calcSliderPos(osdInfo &info, bool paddedFields = false);
     356    uint64_t TranslatePositionAbsToRel(uint64_t absPosition) {
     357        return deleteMap.TranslatePositionAbsToRel(absPosition);
     358    }
     359    uint64_t TranslatePositionRelToAbs(uint64_t relPosition) {
     360        return deleteMap.TranslatePositionRelToAbs(relPosition);
     361    }
    356362
    357363    // Commercial stuff
    358364    void SetAutoCommercialSkip(CommSkipMode autoskip)
  • mythtv/libs/libmythtv/osd.cpp

    diff --git a/mythtv/libs/libmythtv/osd.cpp b/mythtv/libs/libmythtv/osd.cpp
    index 56d6611..68ca122 100644
    a b void OSD::SetValues(const QString &window, QHash<QString,int> &map, 
    344344            found = true;
    345345        }
    346346    }
     347    if (map.contains("rawposition"))
     348    {
     349        MythUIProgressBar *bar = dynamic_cast<MythUIProgressBar *> (win->GetChild("rawposition"));
     350        if (bar)
     351        {
     352            bar->SetVisible(true);
     353            bar->SetStart(0);
     354            bar->SetTotal(1000);
     355            bar->SetUsed(map.value("rawposition"));
     356            found = true;
     357        }
     358    }
    347359
    348360    if (found)
    349361        SetExpiry(window, timeout);
  • mythtv/libs/libmythtv/tv_actions.h

    diff --git a/mythtv/libs/libmythtv/tv_actions.h b/mythtv/libs/libmythtv/tv_actions.h
    index 40cb096..33c61d2 100644
    a b  
    3838#define ACTION_JUMPFFWD             "JUMPFFWD"
    3939#define ACTION_JUMPRWND             "JUMPRWND"
    4040#define ACTION_JUMPBKMRK            "JUMPBKMRK"
     41#define ACTION_SEEKRWNDNOCUTLIST    "SEEKRWNDNOCUTLIST"
     42#define ACTION_SEEKFFWDNOCUTLIST    "SEEKFFWDNOCUTLIST"
     43#define ACTION_JUMPRWNDNOCUTLIST    "JUMPRWNDNOCUTLIST"
     44#define ACTION_JUMPFFWDNOCUTLIST    "JUMPFFWDNOCUTLIST"
    4145#define ACTION_JUMPSTART            "JUMPSTART"
    4246#define ACTION_JUMPTODVDROOTMENU    "JUMPTODVDROOTMENU"
    4347#define ACTION_JUMPTOPOPUPMENU      "JUMPTOPOPUPMENU"
  • mythtv/libs/libmythtv/tv_play.cpp

    diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp
    index f713b42..78aad4d 100644
    a b void TV::InitKeys(void) 
    505505            "Pause"), "P");
    506506    REG_KEY("TV Playback", ACTION_SEEKFFWD, QT_TRANSLATE_NOOP("MythControls",
    507507            "Fast Forward"), "Right");
     508    REG_KEY("TV Playback", ACTION_SEEKFFWDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     509            "Fast Forward ignoring cutlist"), "");
    508510    REG_KEY("TV Playback", ACTION_SEEKRWND, QT_TRANSLATE_NOOP("MythControls",
    509511            "Rewind"), "Left");
     512    REG_KEY("TV Playback", ACTION_SEEKRWNDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     513            "Rewind ignoring cutlist"), "");
    510514    REG_KEY("TV Playback", ACTION_SEEKARB, QT_TRANSLATE_NOOP("MythControls",
    511515            "Arbitrary Seek"), "*");
     516    REG_KEY("TV Playback", "ARBSEEKNOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     517            "Arbitrary Seek ignoring cutlist"), "");
    512518    REG_KEY("TV Playback", ACTION_SEEKABSOLUTE, QT_TRANSLATE_NOOP("MythControls",
    513519            "Seek to a position in seconds"), "");
    514520    REG_KEY("TV Playback", ACTION_CHANNELUP, QT_TRANSLATE_NOOP("MythControls",
    void TV::InitKeys(void) 
    521527            "Switch to the previous channel"), "H");
    522528    REG_KEY("TV Playback", ACTION_JUMPFFWD, QT_TRANSLATE_NOOP("MythControls",
    523529            "Jump ahead"), "PgDown");
     530    REG_KEY("TV Playback", ACTION_JUMPFFWDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     531            "Jump ahead ignoring cutlist"), "");
    524532    REG_KEY("TV Playback", ACTION_JUMPRWND, QT_TRANSLATE_NOOP("MythControls",
    525533            "Jump back"), "PgUp");
     534    REG_KEY("TV Playback", ACTION_JUMPRWNDNOCUTLIST, QT_TRANSLATE_NOOP("MythControls",
     535            "Jump back ignoring cutlist"), "");
     536    REG_KEY("TV Playback", "INFONOCUTLIST", QT_TRANSLATE_NOOP("MythControls",
     537            "Info ignoring cutlist"), "");
    526538    REG_KEY("TV Playback", ACTION_JUMPBKMRK, QT_TRANSLATE_NOOP("MythControls",
    527539            "Jump to bookmark"), "K");
    528540    REG_KEY("TV Playback", "FFWDSTICKY", QT_TRANSLATE_NOOP("MythControls",
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    40134025        }
    40144026    }
    40154027    else if (has_action(ACTION_JUMPRWND, actions))
    4016         DoJumpRWND(ctx);
     4028        DoJumpRWND(ctx, true);
     4029    else if (has_action(ACTION_JUMPRWNDNOCUTLIST, actions))
     4030        DoJumpRWND(ctx, false);
    40174031    else if (has_action(ACTION_JUMPFFWD, actions))
    4018         DoJumpFFWD(ctx);
     4032        DoJumpFFWD(ctx, true);
     4033    else if (has_action(ACTION_JUMPFFWDNOCUTLIST, actions))
     4034        DoJumpFFWD(ctx, false);
    40194035    else if (has_action(ACTION_JUMPBKMRK, actions))
    40204036    {
    40214037        ctx->LockDeletePlayer(__FILE__, __LINE__);
    4022         long long bookmark = ctx->player->GetBookmark();
    4023         long long curloc   = ctx->player->GetFramesPlayed();
     4038        uint64_t bookmark  = ctx->player->GetBookmark();
    40244039        float     rate     = ctx->player->GetFrameRate();
    4025         long long seekloc = (long long) ((bookmark - curloc) / rate);
     4040        float seekloc = ctx->player->TranslatePositionAbsToRel(bookmark) / rate;
    40264041        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    40274042
    40284043        if (bookmark > rate)
    4029             DoSeek(ctx, seekloc, tr("Jump to Bookmark"));
     4044            DoSeek(ctx, seekloc, tr("Jump to Bookmark"), false);
    40304045    }
    40314046    else if (has_action(ACTION_JUMPSTART,actions))
    40324047    {
    4033         long long seekloc = +1;
    4034         ctx->LockDeletePlayer(__FILE__, __LINE__);
    4035         seekloc = (int64_t) (-1.0 * ctx->player->GetFramesPlayed() /
    4036                              ctx->player->GetFrameRate());
    4037         ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    4038 
    4039         if (seekloc <= 0)
    4040             DoSeek(ctx, seekloc, tr("Jump to Beginning"));
     4048        DoSeek(ctx, 0, tr("Jump to Beginning"), false);
    40414049    }
    40424050    else if (has_action(ACTION_CLEAROSD, actions))
    40434051    {
    bool TV::ActiveHandleAction(PlayerContext *ctx, 
    41954203        ChangeTimeStretch(ctx, -1);
    41964204    else if (has_action("MENU", actions))
    41974205        ShowOSDMenu(ctx);
    4198     else if (has_action("INFO", actions))
     4206    else if (has_action("INFO", actions) || has_action("INFONOCUTLIST", actions))
    41994207    {
    42004208        if (HasQueuedInput())
    42014209        {
    4202             DoArbSeek(ctx, ARBSEEK_SET);
     4210            DoArbSeek(ctx, ARBSEEK_SET, !has_action("INFONOCUTLIST", actions));
    42034211        }
    42044212        else
    42054213            ToggleOSD(ctx, true);
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, const QStringList &actions) 
    44374445                ChangeChannel(ctx, CHANNEL_DIRECTION_UP);
    44384446        }
    44394447        else
    4440             DoJumpRWND(ctx);
     4448            DoJumpRWND(ctx, true);
    44414449    }
    44424450    else if (has_action(ACTION_CHANNELDOWN, actions))
    44434451    {
    bool TV::ActivePostQHandleAction(PlayerContext *ctx, const QStringList &actions) 
    44494457                ChangeChannel(ctx, CHANNEL_DIRECTION_DOWN);
    44504458        }
    44514459        else
    4452             DoJumpFFWD(ctx);
     4460            DoJumpFFWD(ctx, true);
    44534461    }
    44544462    else if (has_action("DELETE", actions) && !islivetv)
    44554463    {
    void TV::ProcessNetworkControlCommand(PlayerContext *ctx, 
    46784686        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    46794687
    46804688        if (tokens[2] == "BEGINNING")
    4681             DoSeek(ctx, -fplay, tr("Jump to Beginning"));
    4682         else if (tokens[2] == "FORWARD")
    4683             DoSeek(ctx, ctx->fftime, tr("Skip Ahead"));
    4684         else if (tokens[2] == "BACKWARD")
    4685             DoSeek(ctx, -ctx->rewtime, tr("Skip Back"));
    4686         else if ((tokens[2] == "POSITION") && (tokens.size() == 4) &&
     4689            DoSeek(ctx, 0, tr("Jump to Beginning"), false);
     4690        else if (tokens[2] == "FORWARD" || tokens[2] == "FORWARDNOCUTLIST")
     4691            DoSeek(ctx, ctx->fftime, tr("Skip Ahead"), true, tokens[2] == "FORWARD");
     4692        else if (tokens[2] == "BACKWARD" || tokens[2] == "BACKWARDNOCUTLIST")
     4693            DoSeek(ctx, -ctx->rewtime, tr("Skip Back"), true, tokens[2] == "BACKWARD");
     4694        else if ((tokens[2] == "POSITION" ||
     4695                  tokens[2] == "POSITIONNOCUTLIST") &&
     4696                 (tokens.size() == 4) &&
    46874697                 (tokens[3].contains(QRegExp("^\\d+$"))))
    46884698        {
    4689             DoSeekAbsolute(ctx, tokens[3].toInt());
     4699            DoSeekAbsolute(ctx, tokens[3].toInt(),
     4700                           tokens[2] == "POSITION");
    46904701        }
    46914702    }
    46924703    else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    57205731                          const bool isDVD)
    57215732{
    57225733    const int kRewind = 4, kForward = 8, kSticky = 16, kSlippery = 32,
    5723               kRelative = 64, kAbsolute = 128, kWhenceMask = 3;
     5734              kRelative = 64, kAbsolute = 128, kIgnoreCutlist = 256,
     5735              kWhenceMask = 3;
    57245736    int flags = 0;
    57255737    if (has_action(ACTION_SEEKFFWD, actions))
    57265738        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
     5739    else if (has_action(ACTION_SEEKFFWDNOCUTLIST, actions))
     5740        flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative | kIgnoreCutlist;
    57275741    else if (has_action("FFWDSTICKY", actions))
    57285742        flags = ARBSEEK_END     | kForward | kSticky   | kAbsolute;
    57295743    else if (has_action(ACTION_RIGHT, actions))
    57305744        flags = ARBSEEK_FORWARD | kForward | kSticky   | kRelative;
    57315745    else if (has_action(ACTION_SEEKRWND, actions))
    57325746        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative;
     5747    else if (has_action(ACTION_SEEKRWNDNOCUTLIST, actions))
     5748        flags = ARBSEEK_REWIND  | kRewind  | kSlippery | kRelative | kIgnoreCutlist;
    57335749    else if (has_action("RWNDSTICKY", actions))
    57345750        flags = ARBSEEK_SET     | kRewind  | kSticky   | kAbsolute;
    57355751    else if (has_action(ACTION_LEFT, actions))
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    57405756    int direction = (flags & kRewind) ? -1 : 1;
    57415757    if (HasQueuedInput())
    57425758    {
    5743         DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask));
     5759        DoArbSeek(actx, static_cast<ArbSeekWhence>(flags & kWhenceMask),
     5760                  !(flags & kIgnoreCutlist));
    57445761    }
    57455762    else if (ContextIsPaused(actx, __FILE__, __LINE__))
    57465763    {
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    57555772                             direction * (1.001 / rate);
    57565773            QString message = (flags & kRewind) ? QString(tr("Rewind")) :
    57575774                                                 QString(tr("Forward"));
    5758             DoSeek(actx, time, message);
     5775            DoSeek(actx, time, message, true, !(flags & kIgnoreCutlist));
    57595776        }
    57605777    }
    57615778    else if (flags & kSticky)
    bool TV::SeekHandleAction(PlayerContext *actx, const QStringList &actions, 
    57665783    {
    57675784            if (smartForward)
    57685785                doSmartForward = true;
    5769             DoSeek(actx, -actx->rewtime, tr("Skip Back"));
     5786            DoSeek(actx, -actx->rewtime, tr("Skip Back"),
     5787                   true, !(flags & kIgnoreCutlist));
    57705788    }
    57715789    else
    57725790    {
    57735791        if (smartForward & doSmartForward)
    5774             DoSeek(actx, actx->rewtime, tr("Skip Ahead"));
     5792            DoSeek(actx, actx->rewtime, tr("Skip Ahead"),
     5793                   true, !(flags & kIgnoreCutlist));
    57755794        else
    5776             DoSeek(actx, actx->fftime, tr("Skip Ahead"));
     5795            DoSeek(actx, actx->fftime, tr("Skip Ahead"),
     5796                   true, !(flags & kIgnoreCutlist));
    57775797    }
    57785798    return true;
    57795799}
    57805800
    5781 void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg)
     5801void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg,
     5802                bool timeIsOffset, bool honorCutlist)
    57825803{
    57835804    bool limitkeys = false;
    57845805
    void TV::DoSeek(PlayerContext *ctx, float time, const QString &mesg) 
    57925813        keyRepeatTimer.start();
    57935814        NormalSpeed(ctx);
    57945815        time += StopFFRew(ctx);
     5816        float framerate = ctx->player->GetFrameRate();
     5817        uint64_t currentFrameAbs = ctx->player->GetFramesPlayed();
     5818        uint64_t currentFrameRel = honorCutlist ?
     5819            ctx->player->TranslatePositionAbsToRel(currentFrameAbs) :
     5820            currentFrameAbs;
     5821        int64_t desiredFrameRel = (timeIsOffset ? currentFrameRel : 0) +
     5822            time * framerate + 0.5;
     5823        if (desiredFrameRel < 0)
     5824            desiredFrameRel = 0;
     5825        uint64_t desiredFrameAbs = honorCutlist ?
     5826            ctx->player->TranslatePositionRelToAbs(desiredFrameRel) :
     5827            desiredFrameRel;
     5828        time = ((int64_t)desiredFrameAbs - (int64_t)currentFrameAbs) / framerate;
    57955829        DoPlayerSeek(ctx, time);
    57965830        UpdateOSDSeekMessage(ctx, mesg, kOSDTimeout_Med);
    57975831    }
    57985832}
    57995833
    5800 void TV::DoSeekAbsolute(PlayerContext *ctx, long long seconds)
     5834void TV::DoSeekAbsolute(PlayerContext *ctx, long long seconds, bool honorCutlist)
    58015835{
    58025836    ctx->LockDeletePlayer(__FILE__, __LINE__);
    58035837    if (!ctx->player)
    void TV::DoSeekAbsolute(PlayerContext *ctx, long long seconds) 
    58075841    }
    58085842    seconds -= (ctx->player->GetFramesPlayed() - 1) / ctx->player->GetFrameRate();
    58095843    ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5810     DoSeek(ctx, seconds, tr("Jump To"));
     5844    DoSeek(ctx, seconds, tr("Jump To"), honorCutlist);
    58115845}
    58125846
    5813 void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence)
     5847void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence, bool honorCutlist)
    58145848{
    58155849    bool ok = false;
    58165850    int seek = GetQueuedInputAsInt(&ok);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    58215855    float time = ((seek / 100) * 3600) + ((seek % 100) * 60);
    58225856
    58235857    if (whence == ARBSEEK_FORWARD)
    5824         DoSeek(ctx, time, tr("Jump Ahead"));
     5858        DoSeek(ctx, time, tr("Jump Ahead"), true, honorCutlist);
    58255859    else if (whence == ARBSEEK_REWIND)
    5826         DoSeek(ctx, -time, tr("Jump Back"));
     5860        DoSeek(ctx, -time, tr("Jump Back"), true, honorCutlist);
    58275861    else if (whence == ARBSEEK_END)
    58285862    {
    58295863        ctx->LockDeletePlayer(__FILE__, __LINE__);
    void TV::DoArbSeek(PlayerContext *ctx, ArbSeekWhence whence) 
    58355869        time = (ctx->player->CalcMaxFFTime(LONG_MAX, false) /
    58365870                ctx->player->GetFrameRate()) - time;
    58375871        ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    5838         DoSeek(ctx, time, tr("Jump To"));
     5872        DoSeek(ctx, time, tr("Jump To"), (whence != ARBSEEK_SET), honorCutlist);
    58395873    }
    58405874    else
    5841         DoSeekAbsolute(ctx, time);
     5875        DoSeekAbsolute(ctx, time, honorCutlist);
    58425876}
    58435877
    58445878void TV::NormalSpeed(PlayerContext *ctx)
    bool TV::CommitQueuedInput(PlayerContext *ctx) 
    67636797    {
    67646798        commited = true;
    67656799        if (HasQueuedInput())
     6800            // XXX Should the cutlist be honored?
    67666801            DoArbSeek(ctx, ARBSEEK_FORWARD);
    67676802    }
    67686803    else if (StateIsLiveTV(GetState(ctx)))
    void TV::OSDDialogEvent(int result, QString text, QString action) 
    98009835        SetExitPlayer(true, true);
    98019836    }
    98029837    else if (action == ACTION_JUMPFFWD)
    9803         DoJumpFFWD(actx);
     9838        DoJumpFFWD(actx, true);
     9839    else if (action == ACTION_JUMPFFWDNOCUTLIST)
     9840        DoJumpFFWD(actx, false);
    98049841    else if (action == ACTION_JUMPRWND)
    9805         DoJumpRWND(actx);
     9842        DoJumpRWND(actx, true);
     9843    else if (action == ACTION_JUMPRWNDNOCUTLIST)
     9844        DoJumpRWND(actx, false);
    98069845    else if (action.startsWith("DEINTERLACER"))
    98079846        HandleDeinterlacer(actx, action);
    98089847    else if (action == ACTION_TOGGLEOSDDEBUG)
    void TV::ITVRestart(PlayerContext *ctx, bool isLive) 
    1163311672    ctx->UnlockDeletePlayer(__FILE__, __LINE__);
    1163411673}
    1163511674
    11636 void TV::DoJumpFFWD(PlayerContext *ctx)
     11675void TV::DoJumpFFWD(PlayerContext *ctx, bool honorCutlist)
    1163711676{
    1163811677    if (GetState(ctx) == kState_WatchingDVD)
    1163911678        DVDJumpForward(ctx);
    1164011679    else if (GetNumChapters(ctx) > 0)
    1164111680        DoJumpChapter(ctx, 9999);
    1164211681    else
    11643         DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     11682        DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true, honorCutlist);
    1164411683}
    1164511684
    11646 void TV::DoJumpRWND(PlayerContext *ctx)
     11685void TV::DoJumpRWND(PlayerContext *ctx, bool honorCutlist)
    1164711686{
    1164811687    if (GetState(ctx) == kState_WatchingDVD)
    1164911688        DVDJumpBack(ctx);
    1165011689    else if (GetNumChapters(ctx) > 0)
    1165111690        DoJumpChapter(ctx, -1);
    1165211691    else
    11653         DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     11692        DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true, honorCutlist);
    1165411693}
    1165511694
    1165611695/*  \fn TV::DVDJumpBack(PlayerContext*)
    void TV::DVDJumpBack(PlayerContext *ctx) 
    1167611715        uint chapterLength = dvdrb->GetChapterLength();
    1167711716        if ((titleLength == chapterLength) && chapterLength > 300)
    1167811717        {
    11679             DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"));
     11718            DoSeek(ctx, -ctx->jumptime * 60, tr("Jump Back"), true);
    1168011719        }
    1168111720        else
    1168211721        {
    void TV::DVDJumpForward(PlayerContext *ctx) 
    1171911758             (currentTime < (chapterLength - (ctx->jumptime * 60))) &&
    1172011759             chapterLength > 300)
    1172111760        {
    11722             DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"));
     11761            DoSeek(ctx, ctx->jumptime * 60, tr("Jump Ahead"), true);
    1172311762        }
    1172411763        else
    1172511764        {
  • mythtv/libs/libmythtv/tv_play.h

    diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h
    index f9cedca..ad495b5 100644
    a b class MTV_PUBLIC TV : public QObject 
    383383    ProgramInfo *GetLastProgram(void) const;
    384384
    385385    // Seek, skip, jump, speed
    386     void DoSeek(PlayerContext*, float time, const QString &mesg);
     386    void DoSeek(PlayerContext*, float time, const QString &mesg,
     387                bool timeIsOffset, bool honorCutlist=true);
    387388    bool DoPlayerSeek(PlayerContext*, float time);
    388389    enum ArbSeekWhence {
    389390        ARBSEEK_SET = 0,
    class MTV_PUBLIC TV : public QObject 
    391392        ARBSEEK_FORWARD,
    392393        ARBSEEK_END
    393394    };
    394     void DoSeekAbsolute(PlayerContext *ctx, long long seconds);
    395     void DoArbSeek(PlayerContext*, ArbSeekWhence whence);
    396     void DoJumpFFWD(PlayerContext *ctx);
    397     void DoJumpRWND(PlayerContext *ctx);
     395    void DoSeekAbsolute(PlayerContext *ctx, long long seconds, bool honorCutlist=true);
     396    void DoArbSeek(PlayerContext*, ArbSeekWhence whence, bool honorCutlist=true);
     397    void DoJumpFFWD(PlayerContext *ctx, bool honorCutlist);
     398    void DoJumpRWND(PlayerContext *ctx, bool honorCutlist);
    398399    void NormalSpeed(PlayerContext*);
    399400    void ChangeSpeed(PlayerContext*, int direction);
    400401    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 b711a3c..6f60e2e 100644
    a b  
    519519            <area>770,10,300,30</area>
    520520            <align>right,top</align>
    521521        </textarea>
    522         <textarea name="timedisplay" from="title">
     522        <textarea name="fulltimedisplay" from="title">
    523523            <area>10,50,1060,30</area>
    524524            <align>hcenter,bottom</align>
    525525        </textarea>