Ticket #11713: 11713_v2.patch
| File 11713_v2.patch, 31.3 KB (added by , 11 years ago) |
|---|
-
mythtv/libs/libmyth/programinfo.cpp
diff --git a/mythtv/libs/libmyth/programinfo.cpp b/mythtv/libs/libmyth/programinfo.cpp index 8764134..9757c18 100644
a b uint64_t ProgramInfo::QueryBookmark(uint chanid, const QDateTime &recstartts) 2695 2695 return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key(); 2696 2696 } 2697 2697 2698 /** \brief Gets any progstart position in database, 2699 * unless the ignore progstart flag is set. 2700 * 2701 * \return Progstart position in frames if the query is executed 2702 * and succeeds, zero otherwise. 2703 */ 2704 uint64_t ProgramInfo::QueryProgStart(void) const 2705 { 2706 if (programflags & FL_IGNOREPROGSTART) 2707 return 0; 2708 2709 frm_dir_map_t bookmarkmap; 2710 QueryMarkupMap(bookmarkmap, MARK_UTIL_PROGSTART); 2711 2712 return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key(); 2713 } 2714 2715 /** \brief Gets any lastplaypos position in database, 2716 * unless the ignore lastplaypos flag is set. 2717 * 2718 * \return LastPlayPos position in frames if the query is executed 2719 * and succeeds, zero otherwise. 2720 */ 2721 uint64_t ProgramInfo::QueryLastPlayPos(void) const 2722 { 2723 if (programflags & FL_IGNORELASTPLAYPOS) 2724 return 0; 2725 2726 frm_dir_map_t bookmarkmap; 2727 QueryMarkupMap(bookmarkmap, MARK_UTIL_LASTPLAYPOS); 2728 2729 return (bookmarkmap.isEmpty()) ? 0 : bookmarkmap.begin().key(); 2730 } 2731 2698 2732 /** \brief Queries "dvdbookmark" table for bookmarking DVD serial 2699 2733 * number. Deletes old dvd bookmarks if "delbookmark" is set. 2700 2734 * -
mythtv/libs/libmyth/programinfo.h
diff --git a/mythtv/libs/libmyth/programinfo.h b/mythtv/libs/libmyth/programinfo.h index ce8159d..a37ac05 100644
a b class MPUBLIC ProgramInfo 452 452 453 453 uint32_t GetProgramFlags(void) const { return programflags; } 454 454 ProgramInfoType GetProgramInfoType(void) const 455 { return (ProgramInfoType)((programflags & FL_TYPEMASK) >> 16); }455 { return (ProgramInfoType)((programflags & FL_TYPEMASK) >> 20); } 456 456 bool IsGeneric(void) const; 457 457 bool IsInUsePlaying(void) const { return programflags & FL_INUSEPLAYING;} 458 458 bool IsCommercialFree(void) const { return programflags & FL_CHANCOMMFREE;} … … class MPUBLIC ProgramInfo 489 489 // Quick sets 490 490 void SetTitle(const QString &t) { title = t; title.detach(); } 491 491 void SetProgramInfoType(ProgramInfoType t) 492 { programflags &= ~FL_TYPEMASK; programflags |= ((uint32_t)t<< 16); }492 { programflags &= ~FL_TYPEMASK; programflags |= ((uint32_t)t<<20); } 493 493 void SetPathname(const QString&) const; 494 494 void SetChanID(uint _chanid) { chanid = _chanid; } 495 495 void SetScheduledStartTime(const QDateTime &dt) { startts = dt; } … … class MPUBLIC ProgramInfo 532 532 programflags &= ~FL_IGNOREBOOKMARK; 533 533 programflags |= (ignore) ? FL_IGNOREBOOKMARK : 0; 534 534 } 535 /// \brief If "ignore" is true QueryProgStart() will return 0, otherwise 536 /// QueryProgStart() will return the progstart position if it exists. 537 void SetIgnoreProgStart(bool ignore) 538 { 539 programflags &= ~FL_IGNOREPROGSTART; 540 programflags |= (ignore) ? FL_IGNOREPROGSTART : 0; 541 } 542 /// \brief If "ignore" is true QueryLastPlayPos() will return 0, otherwise 543 /// QueryLastPlayPos() will return the last playback position 544 /// if it exists. 545 void SetIgnoreLastPlayPos(bool ignore) 546 { 547 programflags &= ~FL_IGNORELASTPLAYPOS; 548 programflags |= (ignore) ? FL_IGNORELASTPLAYPOS : 0; 549 } 535 550 virtual void SetRecordingID(uint _recordedid) { recordedid = _recordedid; } 536 551 void SetRecordingStatus(RecStatus::Type status) { recstatus = status; } 537 552 void SetRecordingRuleType(RecordingType type) { rectype = type; } … … class MPUBLIC ProgramInfo 544 559 uint QueryMplexID(void) const; 545 560 QDateTime QueryBookmarkTimeStamp(void) const; 546 561 uint64_t QueryBookmark(void) const; 562 uint64_t QueryProgStart(void) const; 563 uint64_t QueryLastPlayPos(void) const; 547 564 CategoryType QueryCategoryType(void) const; 548 565 QStringList QueryDVDBookmark(const QString &serialid) const; 549 566 bool QueryIsEditing(void) const; … … class MPUBLIC ProgramInfo 658 675 static QMap<QString,bool> QueryJobsRunning(int type); 659 676 static QStringList LoadFromScheduler(const QString &altTable, int recordid); 660 677 661 protected:662 678 // Flagging map support methods 663 679 void QueryMarkupMap(frm_dir_map_t&, MarkTypes type, 664 680 bool merge = false) const; … … class MPUBLIC ProgramInfo 667 683 void ClearMarkupMap(MarkTypes type = MARK_ALL, 668 684 int64_t min_frm = -1, int64_t max_frm = -1) const; 669 685 686 protected: 670 687 // Creates a basename from the start and end times 671 688 QString CreateRecordBasename(const QString &ext) const; 672 689 -
mythtv/libs/libmyth/programtypes.cpp
diff --git a/mythtv/libs/libmyth/programtypes.cpp b/mythtv/libs/libmyth/programtypes.cpp index 26b5357..26d3935 100644
a b QString toString(MarkTypes type) 53 53 case MARK_VIDEO_RATE: return "VIDEO_RATE"; 54 54 case MARK_DURATION_MS: return "DURATION_MS"; 55 55 case MARK_TOTAL_FRAMES: return "TOTAL_FRAMES"; 56 case MARK_UTIL_PROGSTART: return "UTIL_PROGSTART"; 57 case MARK_UTIL_LASTPLAYPOS: return "UTIL_LASTPLAYPOS"; 56 58 } 57 59 58 60 return "unknown"; -
mythtv/libs/libmyth/programtypes.h
diff --git a/mythtv/libs/libmyth/programtypes.h b/mythtv/libs/libmyth/programtypes.h index d85ee94..373d3ad 100644
a b typedef enum { 74 74 MARK_VIDEO_RATE = 32, 75 75 MARK_DURATION_MS = 33, 76 76 MARK_TOTAL_FRAMES = 34, 77 MARK_UTIL_PROGSTART = 40, 78 MARK_UTIL_LASTPLAYPOS = 41, 77 79 } MarkTypes; 78 80 MPUBLIC QString toString(MarkTypes type); 79 81 … … typedef enum FlagMask { 145 147 FL_DUPLICATE = 0x00002000, 146 148 FL_REACTIVATE = 0x00004000, 147 149 FL_IGNOREBOOKMARK = 0x00008000, 150 FL_IGNOREPROGSTART = 0x00010000, 151 FL_IGNORELASTPLAYPOS = 0x00020000, 148 152 // if you move the type mask please edit {Set,Get}ProgramInfoType() 149 FL_TYPEMASK = 0x00 0F0000,150 FL_INUSERECORDING = 0x0 0100000,151 FL_INUSEPLAYING = 0x0 0200000,152 FL_INUSEOTHER = 0x0 0400000,153 FL_TYPEMASK = 0x00F00000, 154 FL_INUSERECORDING = 0x01000000, 155 FL_INUSEPLAYING = 0x02000000, 156 FL_INUSEOTHER = 0x04000000, 153 157 } ProgramFlag; 154 158 155 159 typedef enum ProgramInfoType { -
mythtv/libs/libmythtv/mythplayer.cpp
diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp index e52b3c9..6c6abfb 100644
a b void MythPlayer::EventStart(void) 2879 2879 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 2880 2880 { 2881 2881 if (player_ctx->playingInfo) 2882 { 2883 // When initial playback gets underway, we override the ProgramInfo 2884 // flags such that future calls to GetBookmark() will consider only 2885 // an actual bookmark and not progstart or lastplaypos information. 2882 2886 player_ctx->playingInfo->SetIgnoreBookmark(false); 2887 player_ctx->playingInfo->SetIgnoreProgStart(true); 2888 player_ctx->playingInfo->SetIgnoreLastPlayPos(true); 2889 } 2883 2890 } 2884 2891 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 2885 2892 commBreakMap.LoadMap(player_ctx, framesPlayed); … … uint64_t MythPlayer::GetBookmark(void) 3610 3617 { 3611 3618 player_ctx->LockPlayingInfo(__FILE__, __LINE__); 3612 3619 if (player_ctx->playingInfo) 3620 { 3613 3621 bookmark = player_ctx->playingInfo->QueryBookmark(); 3622 if (bookmark == 0) 3623 bookmark = player_ctx->playingInfo->QueryProgStart(); 3624 if (bookmark == 0) 3625 bookmark = player_ctx->playingInfo->QueryLastPlayPos(); 3626 } 3614 3627 player_ctx->UnlockPlayingInfo(__FILE__, __LINE__); 3615 3628 } 3616 3629 -
mythtv/libs/libmythtv/recorders/recorderbase.cpp
diff --git a/mythtv/libs/libmythtv/recorders/recorderbase.cpp b/mythtv/libs/libmythtv/recorders/recorderbase.cpp index 669c872..a6fc9fa 100644
a b RecorderBase::RecorderBase(TVRec *rec) 56 56 request_pause(false), paused(false), 57 57 request_recording(false), recording(false), 58 58 nextRingBuffer(NULL), nextRecording(NULL), 59 positionMapType(MARK_GOP_BYFRAME) 59 positionMapType(MARK_GOP_BYFRAME), 60 estimatedProgStartMS(0), lastSavedKeyframe(0), lastSavedDuration(0) 60 61 { 61 62 ClearStatistics(); 62 63 QMutexLocker locker(avcodeclock); … … void RecorderBase::SetRecording(const RecordingInfo *pginfo) 114 115 // instance which may lead to the possibility that changes made 115 116 // in the database by one are overwritten by the other 116 117 curRecording = new RecordingInfo(*pginfo); 118 // Compute an estimate of the actual progstart delay for setting the 119 // MARK_UTIL_PROGSTART mark. We can't reliably use 120 // curRecording->GetRecordingStartTime() because the scheduler rounds it 121 // to the nearest minute, so we use the current time instead. 122 estimatedProgStartMS = 123 MythDate::current().msecsTo(curRecording->GetScheduledStartTime()); 117 124 RecordingFile *recFile = curRecording->GetRecordingFile(); 118 125 recFile->m_containerFormat = m_containerFormat; 119 126 recFile->Save(); … … void RecorderBase::SavePositionMap(bool force, bool finished) 579 586 bool needToSave = force; 580 587 positionMapLock.lock(); 581 588 582 uint delta_size = positionMapDelta.size();589 bool has_delta = !positionMapDelta.empty(); 583 590 // set pm_elapsed to a fake large value if the timer hasn't yet started 584 591 uint pm_elapsed = (positionMapTimer.isRunning()) ? 585 592 positionMapTimer.elapsed() : ~0; 586 593 // save on every 1.5 seconds if in the first few frames of a recording 587 594 needToSave |= (positionMap.size() < 30) && 588 (delta_size >= 1)&& (pm_elapsed >= 1500);595 has_delta && (pm_elapsed >= 1500); 589 596 // save every 10 seconds later on 590 needToSave |= (delta_size >= 1)&& (pm_elapsed >= 10000);597 needToSave |= has_delta && (pm_elapsed >= 10000); 591 598 // Assume that durationMapDelta is the same size as 592 599 // positionMapDelta and implicitly use the same logic about when 593 600 // to same durationMapDelta. … … void RecorderBase::SavePositionMap(bool force, bool finished) 595 602 if (curRecording && needToSave) 596 603 { 597 604 positionMapTimer.start(); 598 if ( delta_size)605 if (has_delta) 599 606 { 600 607 // copy the delta map because most times we are called it will be in 601 608 // another thread and we don't want to lock the main recorder thread … … void RecorderBase::SavePositionMap(bool force, bool finished) 609 616 curRecording->SavePositionMapDelta(deltaCopy, positionMapType); 610 617 curRecording->SavePositionMapDelta(durationDeltaCopy, 611 618 MARK_DURATION_MS); 619 620 TryWriteProgStartMark(durationDeltaCopy); 612 621 } 613 622 else 614 623 { … … void RecorderBase::SavePositionMap(bool force, bool finished) 626 635 } 627 636 } 628 637 638 void RecorderBase::TryWriteProgStartMark(const frm_pos_map_t &durationDeltaCopy) 639 { 640 // Note: all log strings contain "progstart mark" for searching. 641 if (estimatedProgStartMS <= 0) 642 { 643 // Do nothing because no progstart mark is needed. 644 LOG(VB_RECORD, LOG_DEBUG, 645 QString("No progstart mark needed because delta=%1") 646 .arg(estimatedProgStartMS)); 647 return; 648 } 649 frm_pos_map_t::const_iterator last_it = durationDeltaCopy.end(); 650 --last_it; 651 long long bookmarkFrame = 0; 652 LOG(VB_RECORD, LOG_DEBUG, 653 QString("durationDeltaCopy.begin() = (%1,%2)") 654 .arg(durationDeltaCopy.begin().key()) 655 .arg(durationDeltaCopy.begin().value())); 656 if (estimatedProgStartMS > *last_it) 657 { 658 // Do nothing because we haven't reached recstartts yet. 659 LOG(VB_RECORD, LOG_DEBUG, 660 QString("No progstart mark yet because estimatedProgStartMS=%1 " 661 "and *last_it=%2") 662 .arg(estimatedProgStartMS).arg(*last_it)); 663 } 664 else if (lastSavedDuration <= estimatedProgStartMS && 665 estimatedProgStartMS < *durationDeltaCopy.begin()) 666 { 667 // Set progstart mark @ lastSavedKeyframe 668 LOG(VB_RECORD, LOG_DEBUG, 669 QString("Set progstart mark=%1 because %2<=%3<%4") 670 .arg(lastSavedKeyframe).arg(lastSavedDuration) 671 .arg(estimatedProgStartMS).arg(*durationDeltaCopy.begin())); 672 bookmarkFrame = lastSavedKeyframe; 673 } 674 else if (*durationDeltaCopy.begin() <= estimatedProgStartMS && 675 estimatedProgStartMS < *last_it) 676 { 677 frm_pos_map_t::const_iterator upper_it = durationDeltaCopy.begin(); 678 for (; upper_it != durationDeltaCopy.end(); ++upper_it) 679 { 680 if (*upper_it > estimatedProgStartMS) 681 { 682 --upper_it; 683 // Set progstart mark @ upper_it.key() 684 LOG(VB_RECORD, LOG_DEBUG, 685 QString("Set progstart mark=%1 because " 686 "estimatedProgStartMS=%2 and upper_it.value()=%3") 687 .arg(upper_it.key()).arg(estimatedProgStartMS) 688 .arg(upper_it.value())); 689 bookmarkFrame = upper_it.key(); 690 break; 691 } 692 } 693 } 694 else 695 { 696 // do nothing 697 LOG(VB_RECORD, LOG_DEBUG, "No progstart mark due to fallthrough"); 698 } 699 if (bookmarkFrame) 700 { 701 frm_dir_map_t progStartMap; 702 progStartMap[bookmarkFrame] = MARK_UTIL_PROGSTART; 703 curRecording->SaveMarkupMap(progStartMap, MARK_UTIL_PROGSTART); 704 } 705 lastSavedKeyframe = last_it.key(); 706 lastSavedDuration = last_it.value(); 707 LOG(VB_RECORD, LOG_DEBUG, 708 QString("Setting lastSavedKeyframe=%1 lastSavedDuration=%2 " 709 "for progstart mark calculations") 710 .arg(lastSavedKeyframe).arg(lastSavedDuration)); 711 } 712 629 713 void RecorderBase::AspectChange(uint aspect, long long frame) 630 714 { 631 715 MarkTypes mark = MARK_ASPECT_4_3; -
mythtv/libs/libmythtv/recorders/recorderbase.h
diff --git a/mythtv/libs/libmythtv/recorders/recorderbase.h b/mythtv/libs/libmythtv/recorders/recorderbase.h index 8d00836..9931413 100644
a b class MTV_PUBLIC RecorderBase : public QRunnable 292 292 */ 293 293 void SetTotalFrames(uint64_t total_frames); 294 294 295 void TryWriteProgStartMark(const frm_pos_map_t &durationDeltaCopy); 296 295 297 TVRec *tvrec; 296 298 RingBuffer *ringBuffer; 297 299 bool weMadeBuffer; … … class MTV_PUBLIC RecorderBase : public QRunnable 341 343 frm_pos_map_t durationMapDelta; 342 344 MythTimer positionMapTimer; 343 345 346 // ProgStart mark support 347 qint64 estimatedProgStartMS; 348 long long lastSavedKeyframe; 349 long long lastSavedDuration; 350 344 351 // Statistics 345 352 // Note: Once we enter RecorderBase::run(), only that thread can 346 353 // update these values safely. These values are read in that thread -
mythtv/libs/libmythtv/tv_play.cpp
diff --git a/mythtv/libs/libmythtv/tv_play.cpp b/mythtv/libs/libmythtv/tv_play.cpp index c9ee3de..138aeb2 100644
a b const uint TV::kEndOfPlaybackFirstCheckTimer = 60000; 137 137 #else 138 138 const uint TV::kEndOfPlaybackFirstCheckTimer = 5000; 139 139 #endif 140 const uint TV::kSaveLastPlayPosTimeout = 30000; 140 141 141 142 /** 142 143 * \brief stores last program info. maintains info so long as … … bool TV::StartTV(ProgramInfo *tvrec, uint flags, 341 342 { 342 343 curProgram = new ProgramInfo(*tvrec); 343 344 curProgram->SetIgnoreBookmark(flags & kStartTVIgnoreBookmark); 345 curProgram->SetIgnoreProgStart(flags & kStartTVIgnoreProgStart); 346 curProgram->SetIgnoreLastPlayPos(flags & kStartTVIgnoreLastPlayPos); 344 347 } 345 348 346 349 GetMythMainWindow()->PauseIdleTimer(true); … … TV::TV(void) 1064 1067 endOfPlaybackTimerId(0), embedCheckTimerId(0), 1065 1068 endOfRecPromptTimerId(0), videoExitDialogTimerId(0), 1066 1069 pseudoChangeChanTimerId(0), speedChangeTimerId(0), 1067 errorRecoveryTimerId(0), exitPlayerTimerId(0) 1070 errorRecoveryTimerId(0), exitPlayerTimerId(0), 1071 saveLastPlayPosTimerId(0) 1068 1072 { 1069 1073 LOG(VB_GENERAL, LOG_INFO, LOC + "Creating TV object"); 1070 1074 ctorTime.start(); … … bool TV::Init(bool createWindow) 1326 1330 errorRecoveryTimerId = StartTimer(kErrorRecoveryCheckFrequency, __LINE__); 1327 1331 lcdTimerId = StartTimer(1, __LINE__); 1328 1332 speedChangeTimerId = StartTimer(kSpeedChangeCheckFrequency, __LINE__); 1333 saveLastPlayPosTimerId = StartTimer(kSaveLastPlayPosTimeout, __LINE__); 1329 1334 1330 1335 LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end"); 1331 1336 return true; … … void TV::timerEvent(QTimerEvent *te) 2777 2782 HandleSpeedChangeTimerEvent(); 2778 2783 else if (timer_id == pipChangeTimerId) 2779 2784 HandlePxPTimerEvent(); 2785 else if (timer_id == saveLastPlayPosTimerId) 2786 HandleSaveLastPlayPosEvent(); 2780 2787 else 2781 2788 handled = false; 2782 2789 … … void TV::PrepareToExitPlayer(PlayerContext *ctx, int line, BookmarkAction bookma 3321 3328 // Don't consider ourselves at the end if the recording is 3322 3329 // in-progress. 3323 3330 at_end &= !StateIsRecording(GetState(ctx)); 3331 bool clear_lastplaypos = true; 3324 3332 if (at_end && allow_clear_at_end) 3325 3333 SetBookmark(ctx, true); 3326 if (!at_end && allow_set_before_end)3334 else if (!at_end && allow_set_before_end) 3327 3335 SetBookmark(ctx, false); 3336 else 3337 clear_lastplaypos = false; 3338 // If we are setting a bookmark upon exit (or equivalently clearing 3339 // it due to exiting at the end), we clean up the unnecessary 3340 // lastplaypos mark. 3341 if (clear_lastplaypos && ctx->playingInfo) 3342 ctx->playingInfo->ClearMarkupMap(MARK_UTIL_LASTPLAYPOS); 3328 3343 } 3329 3344 if (db_auto_set_watched) 3330 3345 ctx->player->SetWatched(); … … bool TV::HandleOSDVideoExit(PlayerContext *ctx, QString action) 13383 13398 return hide; 13384 13399 } 13385 13400 13401 void TV::HandleSaveLastPlayPosEvent(void) 13402 { 13403 // Helper class to save the latest playback position (in a background thread 13404 // to avoid playback glitches). The ctor makes a copy of the ProgramInfo 13405 // struct to avoid race conditions if playback ends and deletes objects 13406 // before or while the background thread runs. 13407 class PositionSaver : public QRunnable 13408 { 13409 public: 13410 PositionSaver(const ProgramInfo &pginfo, uint64_t frame) : 13411 m_pginfo(pginfo), m_frame(frame) {} 13412 virtual void run(void) 13413 { 13414 LOG(VB_PLAYBACK, LOG_DEBUG, 13415 QString("PositionSaver frame=%1").arg(m_frame)); 13416 frm_dir_map_t lastPlayPosMap; 13417 lastPlayPosMap[m_frame] = MARK_UTIL_LASTPLAYPOS; 13418 m_pginfo.ClearMarkupMap(MARK_UTIL_LASTPLAYPOS); 13419 m_pginfo.SaveMarkupMap(lastPlayPosMap, MARK_UTIL_LASTPLAYPOS); 13420 } 13421 private: 13422 const ProgramInfo m_pginfo; 13423 const uint64_t m_frame; 13424 }; 13425 13426 PlayerContext *mctx = GetPlayerReadLock(0, __FILE__, __LINE__); 13427 for (uint i = 0; mctx && i < player.size(); ++i) 13428 { 13429 PlayerContext *ctx = GetPlayer(mctx, i); 13430 ctx->LockDeletePlayer(__FILE__, __LINE__); 13431 bool playing = ctx->player && !ctx->player->IsPaused(); 13432 if (playing) // Don't bother saving lastplaypos while paused 13433 { 13434 uint64_t framesPlayed = ctx->player->GetFramesPlayed(); 13435 MThreadPool::globalInstance()-> 13436 start(new PositionSaver(*ctx->playingInfo, framesPlayed), 13437 "PositionSaver"); 13438 } 13439 ReturnPlayerLock(ctx); 13440 } 13441 ReturnPlayerLock(mctx); 13442 13443 QMutexLocker locker(&timerIdLock); 13444 KillTimer(saveLastPlayPosTimerId); 13445 saveLastPlayPosTimerId = StartTimer(kSaveLastPlayPosTimeout, __LINE__); 13446 } 13447 13386 13448 void TV::SetLastProgram(const ProgramInfo *rcinfo) 13387 13449 { 13388 13450 QMutexLocker locker(&lastProgramLock); -
mythtv/libs/libmythtv/tv_play.h
diff --git a/mythtv/libs/libmythtv/tv_play.h b/mythtv/libs/libmythtv/tv_play.h index 8ab38b1..339aee5 100644
a b enum { 115 115 kStartTVInPlayList = 0x02, 116 116 kStartTVByNetworkCommand = 0x04, 117 117 kStartTVIgnoreBookmark = 0x08, 118 kStartTVIgnoreProgStart = 0x10, 119 kStartTVIgnoreLastPlayPos= 0x20, 118 120 }; 119 121 120 122 class AskProgramInfo … … class MTV_PUBLIC TV : public QObject, public MenuItemDisplayer 409 411 bool HandlePxPTimerEvent(void); 410 412 bool HandleLCDTimerEvent(void); 411 413 void HandleLCDVolumeTimerEvent(void); 414 void HandleSaveLastPlayPosEvent(); 412 415 413 416 // Commands used by frontend UI screens (PlaybackBox, GuideGrid etc) 414 417 void EditSchedule(const PlayerContext*, … … class MTV_PUBLIC TV : public QObject, public MenuItemDisplayer 979 982 volatile int speedChangeTimerId; 980 983 volatile int errorRecoveryTimerId; 981 984 mutable volatile int exitPlayerTimerId; 985 volatile int saveLastPlayPosTimerId; 982 986 TimerContextMap stateChangeTimerId; 983 987 TimerContextMap signalMonitorTimerId; 984 988 … … class MTV_PUBLIC TV : public QObject, public MenuItemDisplayer 1095 1099 static const uint kErrorRecoveryCheckFrequency; 1096 1100 static const uint kEndOfRecPromptCheckFrequency; 1097 1101 static const uint kEndOfPlaybackFirstCheckTimer; 1102 static const uint kSaveLastPlayPosTimeout; 1098 1103 }; 1099 1104 1100 1105 #endif -
mythtv/programs/mythfrontend/playbackbox.cpp
diff --git a/mythtv/programs/mythfrontend/playbackbox.cpp b/mythtv/programs/mythfrontend/playbackbox.cpp index 1050b4a..360d457 100644
a b bool PlaybackBox::Create() 556 556 connect(m_recordingList, SIGNAL(itemSelected(MythUIButtonListItem*)), 557 557 SLOT(ItemSelected(MythUIButtonListItem*))); 558 558 connect(m_recordingList, SIGNAL(itemClicked(MythUIButtonListItem*)), 559 SLOT(PlayFromBookmark (MythUIButtonListItem*)));559 SLOT(PlayFromBookmarkOrProgStart(MythUIButtonListItem*))); 560 560 connect(m_recordingList, SIGNAL(itemVisible(MythUIButtonListItem*)), 561 561 SLOT(ItemVisible(MythUIButtonListItem*))); 562 562 connect(m_recordingList, SIGNAL(itemLoaded(MythUIButtonListItem*)), … … void PlaybackBox::playSelectedPlaylist(bool _random) 2197 2197 this, new MythEvent("PLAY_PLAYLIST")); 2198 2198 } 2199 2199 2200 void PlaybackBox::PlayFromBookmarkOrProgStart(MythUIButtonListItem *item) 2201 { 2202 if (!item) 2203 item = m_recordingList->GetItemCurrent(); 2204 2205 if (!item) 2206 return; 2207 2208 ProgramInfo *pginfo = item->GetData().value<ProgramInfo *>(); 2209 2210 const bool ignoreBookmark = false; 2211 const bool ignoreProgStart = false; 2212 const bool ignoreLastPlayPos = true; 2213 const bool underNetworkControl = false; 2214 if (pginfo) 2215 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 2216 underNetworkControl); 2217 } 2218 2200 2219 void PlaybackBox::PlayFromBookmark(MythUIButtonListItem *item) 2201 2220 { 2202 2221 if (!item) … … void PlaybackBox::PlayFromBookmark(MythUIButtonListItem *item) 2207 2226 2208 2227 ProgramInfo *pginfo = item->GetData().value<ProgramInfo *>(); 2209 2228 2229 const bool ignoreBookmark = false; 2230 const bool ignoreProgStart = true; 2231 const bool ignoreLastPlayPos = true; 2232 const bool underNetworkControl = false; 2210 2233 if (pginfo) 2211 PlayX(*pginfo, false, false); 2234 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 2235 underNetworkControl); 2212 2236 } 2213 2237 2214 2238 void PlaybackBox::PlayFromBeginning(MythUIButtonListItem *item) … … void PlaybackBox::PlayFromBeginning(MythUIButtonListItem *item) 2221 2245 2222 2246 ProgramInfo *pginfo = item->GetData().value<ProgramInfo *>(); 2223 2247 2248 const bool ignoreBookmark = true; 2249 const bool ignoreProgStart = true; 2250 const bool ignoreLastPlayPos = true; 2251 const bool underNetworkControl = false; 2252 if (pginfo) 2253 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 2254 underNetworkControl); 2255 } 2256 2257 void PlaybackBox::PlayFromLastPlayPos(MythUIButtonListItem *item) 2258 { 2259 if (!item) 2260 item = m_recordingList->GetItemCurrent(); 2261 2262 if (!item) 2263 return; 2264 2265 ProgramInfo *pginfo = item->GetData().value<ProgramInfo *>(); 2266 2267 const bool ignoreBookmark = true; 2268 const bool ignoreProgStart = true; 2269 const bool ignoreLastPlayPos = false; 2270 const bool underNetworkControl = false; 2224 2271 if (pginfo) 2225 PlayX(*pginfo, true, false); 2272 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 2273 underNetworkControl); 2226 2274 } 2227 2275 2228 2276 void PlaybackBox::PlayX(const ProgramInfo &pginfo, 2229 2277 bool ignoreBookmark, 2278 bool ignoreProgStart, 2279 bool ignoreLastPlayPos, 2230 2280 bool underNetworkControl) 2231 2281 { 2232 2282 if (!m_player) 2233 2283 { 2234 Play(pginfo, false, ignoreBookmark, underNetworkControl); 2284 Play(pginfo, false, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 2285 underNetworkControl); 2235 2286 return; 2236 2287 } 2237 2288 … … void PlaybackBox::PlayX(const ProgramInfo &pginfo, 2242 2293 ignoreBookmark ? "1" : "0"); 2243 2294 m_player_selected_new_show.push_back( 2244 2295 underNetworkControl ? "1" : "0"); 2296 // XXX add anything for ignoreProgStart and ignoreLastPlayPos? 2245 2297 } 2246 2298 Close(); 2247 2299 } … … void PlaybackBox::selected(MythUIButtonListItem *item) 2324 2376 if (!item) 2325 2377 return; 2326 2378 2327 PlayFromBookmark (item);2379 PlayFromBookmarkOrProgStart(item); 2328 2380 } 2329 2381 2330 2382 void PlaybackBox::popupClosed(QString which, int result) … … void PlaybackBox::ShowGroupPopup() 2412 2464 2413 2465 bool PlaybackBox::Play( 2414 2466 const ProgramInfo &rec, 2415 bool inPlaylist, bool ignoreBookmark, bool underNetworkControl) 2467 bool inPlaylist, bool ignoreBookmark, bool ignoreProgStart, 2468 bool ignoreLastPlayPos, bool underNetworkControl) 2416 2469 { 2417 2470 bool playCompleted = false; 2418 2471 … … bool PlaybackBox::Play( 2444 2497 uint flags = 2445 2498 (inPlaylist ? kStartTVInPlayList : kStartTVNoFlags) | 2446 2499 (underNetworkControl ? kStartTVByNetworkCommand : kStartTVNoFlags) | 2500 (ignoreLastPlayPos ? kStartTVIgnoreLastPlayPos: kStartTVNoFlags) | 2501 (ignoreProgStart ? kStartTVIgnoreProgStart : kStartTVNoFlags) | 2447 2502 (ignoreBookmark ? kStartTVIgnoreBookmark : kStartTVNoFlags); 2448 2503 2449 2504 playCompleted = TV::StartTV(&tvrec, flags); … … MythMenu* PlaybackBox::createPlayFromMenu() 2912 2967 2913 2968 MythMenu *menu = new MythMenu(title, this, "slotmenu"); 2914 2969 2970 if (pginfo->IsBookmarkSet()) 2915 2971 menu->AddItem(tr("Play from bookmark"), SLOT(PlayFromBookmark())); 2916 2972 menu->AddItem(tr("Play from beginning"), SLOT(PlayFromBeginning())); 2973 if (pginfo->QueryLastPlayPos()) 2974 menu->AddItem(tr("Play from last played position"), 2975 SLOT(PlayFromLastPlayPos())); 2917 2976 2918 2977 return menu; 2919 2978 } … … void PlaybackBox::ShowActionPopup(const ProgramInfo &pginfo) 3149 3208 3150 3209 if (!sameProgram) 3151 3210 { 3152 if (pginfo.IsBookmarkSet() )3211 if (pginfo.IsBookmarkSet() || pginfo.QueryLastPlayPos()) 3153 3212 m_popupMenu->AddItem(tr("Play from..."), NULL, createPlayFromMenu()); 3154 3213 else 3155 m_popupMenu->AddItem(tr("Play"), SLOT(PlayFromBookmark())); 3214 m_popupMenu->AddItem(tr("Play"), 3215 SLOT(PlayFromBookmarkOrProgStart())); 3156 3216 } 3157 3217 3158 3218 if (!m_player) … … void PlaybackBox::processNetworkControlCommand(const QString &command) 3743 3803 3744 3804 pginfo.SetPathname(pginfo.GetPlaybackURL()); 3745 3805 3746 bool ignoreBookmark = (tokens[1] == "PLAY"); 3747 PlayX(pginfo, ignoreBookmark, true); 3806 const bool ignoreBookmark = (tokens[1] == "PLAY"); 3807 const bool ignoreProgStart = true; 3808 const bool ignoreLastPlayPos = true; 3809 const bool underNetworkControl = true; 3810 PlayX(pginfo, ignoreBookmark, ignoreProgStart, 3811 ignoreLastPlayPos, underNetworkControl); 3748 3812 } 3749 3813 else 3750 3814 { … … bool PlaybackBox::keyPressEvent(QKeyEvent *event) 3877 3941 if (action == "DELETE") 3878 3942 deleteSelected(m_recordingList->GetItemCurrent()); 3879 3943 else if (action == ACTION_PLAYBACK) 3880 PlayFromBookmark ();3944 PlayFromBookmarkOrProgStart(); 3881 3945 else if (action == "DETAILS" || action == "INFO") 3882 3946 ShowDetails(); 3883 3947 else if (action == "CUSTOMEDIT") … … void PlaybackBox::customEvent(QEvent *event) 4154 4218 else if (pginfo) 4155 4219 { 4156 4220 playnext = false; 4157 Play(*pginfo, kCheckForPlaylistAction == cat, false, false); 4221 const bool ignoreBookmark = false; 4222 const bool ignoreProgStart = false; 4223 const bool ignoreLastPlayPos = true; 4224 const bool underNetworkControl = false; 4225 Play(*pginfo, kCheckForPlaylistAction == cat, 4226 ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, 4227 underNetworkControl); 4158 4228 } 4159 4229 } 4160 4230 … … void PlaybackBox::customEvent(QEvent *event) 4183 4253 } 4184 4254 4185 4255 ProgramInfo *pginfo = FindProgramInUILists(recordingID); 4256 const bool ignoreBookmark = false; 4257 const bool ignoreProgStart = true; 4258 const bool ignoreLastPlayPos = true; 4259 const bool underNetworkControl = false; 4186 4260 if (pginfo) 4187 Play(*pginfo, true, false, false); 4261 Play(*pginfo, true, ignoreBookmark, ignoreProgStart, 4262 ignoreLastPlayPos, underNetworkControl); 4188 4263 } 4189 4264 else if ((message == "SET_PLAYBACK_URL") && (me->ExtraDataCount() == 2)) 4190 4265 { -
mythtv/programs/mythfrontend/playbackbox.h
diff --git a/mythtv/programs/mythfrontend/playbackbox.h b/mythtv/programs/mythfrontend/playbackbox.h index 18ae480..44a41e2 100644
a b class PlaybackBox : public ScheduleCommon 140 140 void ItemVisible(MythUIButtonListItem *item); 141 141 void ItemLoaded(MythUIButtonListItem *item); 142 142 void selected(MythUIButtonListItem *item); 143 void PlayFromBookmarkOrProgStart(MythUIButtonListItem *item = NULL); 143 144 void PlayFromBookmark(MythUIButtonListItem *item = NULL); 144 145 void PlayFromBeginning(MythUIButtonListItem *item = NULL); 146 void PlayFromLastPlayPos(MythUIButtonListItem *item = NULL); 145 147 void deleteSelected(MythUIButtonListItem *item); 146 148 147 149 void SwitchList(void); … … class PlaybackBox : public ScheduleCommon 270 272 271 273 void PlayX(const ProgramInfo &rec, 272 274 bool ignoreBookmark, 275 bool ignoreProgStart, 276 bool ignoreLastPlayPos, 273 277 bool underNetworkControl); 274 278 275 279 bool Play(const ProgramInfo &rec, 276 280 bool inPlaylist, 277 281 bool ignoreBookmark, 282 bool ignoreProgStart, 283 bool ignoreLastPlayPos, 278 284 bool underNetworkControl); 279 285 280 286 virtual ProgramInfo *GetCurrentProgram(void) const;
