Skip to content
This repository

Cleanup ISO stack resume code #1099

Merged
merged 2 commits into from about 2 years ago

3 participants

Voyager1 Cory Fields jmarshallnz
Voyager1
Collaborator

this pull request addresses a number of things in the sphere of resume-play of ISO stacks.

1) move the intelligence down from GUIWindowVideoBase to the VideoDatabase. All we need to know in the GUIWindowVideoBase is what to do with a Bookmark that contains a partnumber > 0.
The VideoDatabase methods GetBookmarksForFile and GetResumePoint know how to deal with ISO stacks now, which makes the code more reusable for non-GUI callers.

2) the resume "flag" as well as "percent complete" for an ISO stack (the little white triangle in Confluence lists) now correctly shows. This was not the case due to the VideoInfoTag resume bookmark not set (prior to the code changes described above in 1). The rule is that the bookmark of the "highest" part counts.

3) additional code cleanup and refactoring - see comments below.

Cory Fields
Owner
theuni commented

Not my area of code to comment on, but kudos on splitting out the whitespace. That makes all the difference for review.

Voyager1
Collaborator

I've added more commits:

  • moving the GetResumeItemOffset code to a more logical place i.e. VideoDatabase. This way Application doesn't have to call GUIWindowVideoBase any longer
  • got rid of the crazy bit manipulation to code the part number as part of the startoffset.
Voyager1
Collaborator

the work is done. I've added one final commit to make sure the SaveFileStateJob properly updates the list. The reason is that for an ISO stack, the current item is actually the part being played, which in itself does not show up in the library list. Therefore, we need to notify the list to update that stack item. Otherwise, we have unexpected results with a bookmark of the "wrong part" being used (unless you reload the list by stepping out and coming back).

jmarshallnz
Owner

On the whole it looks nice. Please squash down the fixup commits and I'll give it another going over.

The only thing I don't particularly like is the non-videodb code in the videodatabase. Not sure if there's a "nice" way to deal with that though.

Voyager1
Collaborator

hi jmarshall - thanks for the code review. I've addressed the pointer comment and retested the code. Commits are squashed.

Regarding the videodatabase code, I agree, I've used Directory/FileItem classes to parse out the stack parts and also there's two new methods that take FileItem ptrs as arguments (the code copied down from GUIWindowVideoBase). The only way I see is to pass a VideoInfoTag instead of a FileItem ptr. But I would then have to move some checking code back to GUIWindowVideoBase (and wherever else this is called).

Voyager1
Collaborator

any other comments - if not, can we assign it to the July milestone?

Voyager1
Collaborator

@jmarshallnz - I've addressed all your comments (I believe).

  • The missing delete is addressed through a smart pointer, consistent with other code.
  • The vector is now cleared using clear()
  • The CApplication member (now protected) is no longer read by another thread, but passed by value to the savefilestatejob.

note: I rebased & left this for your review as a separate commit. When you're ok with final code, I'll squash before you pull.

jmarshallnz
Owner

Fixes look OK - rebase down and I'll give it another overview in case I've missed a simpler way to do it (I don't think so though - ISO stacks are really messy)

Voyager1
Collaborator

@jmarshallnz - done - rebased and squashed (except indentations for easy review)

jmarshallnz
Owner

Ok, the code looks OK, but I really think the two new functions to VideoDatabase don't really belong there - eg GetResumeItemOffset has a path that doesn't hit the db at all (and thus HasResumeItemOffset also has such a path).

IMO having those as statics in VideoBase seems just as reasonable - the only addition I think would be some videodb open/closing internal to GetResumeItemOffset, rather than being external?

Voyager1
Collaborator

@jmarshallnz - once again, done.

jmarshallnz
Owner

Forget to push?

Voyager1
Collaborator

no, it's all there. See commit 02eff8f

jmarshallnz
Owner

Sorry, I wasn't clear (thus didn't notice the difference) - the two statics should be in CGUIWindowVideoBase rather than CVideoDatabase.

Voyager1
Collaborator

ah. The whole point was move them out of CGUIWindowVideoBase because CApplication calls them. I don't like that, as it violates the layering.
EDIT:
let me know if you prefer CApplication calling CGUIWindowVideoBase - I can make that change but it wouldn't make me happy :-(

Voyager1
Collaborator

I could also move the code back to CGUIWindowVideoBase as you suggest and have CApplication call a stripped down version of it (essentially the part that gets the Bookmark from the VideoDatabase. That would probably be the best way overall.

Voyager1
Collaborator

@jmarshallnz - once again, I have implemented your comments, I believe it must be ready for pulling now ;-)

jmarshallnz
Owner

Looks good.

jmarshallnz jmarshallnz merged commit 76f766f into from
Voyager1 Voyager1 deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 2 unique commits by 1 author.

Jul 05, 2012
Voyager-xbmc clean up resume play for stacked ISO files 0062d8b
Voyager-xbmc apply indentations after resume stacked ISO modifications 1684f44
This page is out of date. Refresh to see the latest.
38 xbmc/Application.cpp
@@ -370,6 +370,7 @@ CApplication::CApplication(void)
370 370 #endif
371 371 #endif
372 372 , m_itemCurrentFile(new CFileItem)
  373 + , m_stackFileItemToUpdate(new CFileItem)
373 374 , m_progressTrackingVideoResumeBookmark(*new CBookmark)
374 375 , m_progressTrackingItem(new CFileItem)
375 376 , m_videoInfoScanner(new CVideoInfoScanner)
@@ -3605,26 +3606,35 @@ bool CApplication::PlayStack(const CFileItem& item, bool bRestart)
3605 3606 CFileItemList movieList;
3606 3607 dir.GetDirectory(item.GetPath(), movieList);
3607 3608
3608   - int selectedFile = 1; // if playing from beginning, play file 1.
3609   - long startoffset = item.m_lStartOffset;
  3609 + // first assume values passed to the stack
  3610 + int selectedFile = item.m_lStartPartNumber;
  3611 + int startoffset = item.m_lStartOffset;
3610 3612
3611   - // We instructed the stack to resume.
  3613 + // check if we instructed the stack to resume from default
3612 3614 if (startoffset == STARTOFFSET_RESUME) // selected file is not specified, pick the 'last' resume point
3613   - startoffset = CGUIWindowVideoBase::GetResumeItemOffset(&item);
3614   -
3615   - if (startoffset & 0xF0000000) /* selected part is specified as a flag */
3616 3615 {
3617   - selectedFile = (startoffset>>28);
3618   - startoffset = startoffset & ~0xF0000000;
3619   -
3620   - // set startoffset in movieitem. The remaining startoffset is either 0 (just play part from beginning) or positive (then we use STARTOFFSET_RESUME).
3621   - if (selectedFile > 0 && selectedFile <= (int)movieList.Size())
3622   - movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
  3616 + if (dbs.Open())
  3617 + {
  3618 + CBookmark bookmark;
  3619 + if (dbs.GetResumeBookMark(item.GetPath(), bookmark))
  3620 + {
  3621 + startoffset = (int)(bookmark.timeInSeconds*75);
  3622 + selectedFile = bookmark.partNumber;
  3623 + }
  3624 + dbs.Close();
  3625 + }
  3626 + else
  3627 + CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
3623 3628 }
3624 3629
3625   - // finally play selected item
  3630 + // set startoffset in movieitem, track stack item for updating purposes, and finally play disc part
3626 3631 if (selectedFile > 0 && selectedFile <= (int)movieList.Size())
  3632 + {
  3633 + movieList[selectedFile - 1]->m_lStartOffset = startoffset > 0 ? STARTOFFSET_RESUME : 0;
  3634 + movieList[selectedFile - 1]->SetProperty("stackFileItemToUpdate", true);
  3635 + *m_stackFileItemToUpdate = item;
3627 3636 return PlayFile(*(movieList[selectedFile - 1]));
  3637 + }
3628 3638 }
3629 3639 // case 2: all other stacks
3630 3640 else
@@ -4290,6 +4300,7 @@ void CApplication::SaveFileState(bool bForeground /* = false */)
4290 4300 if (bForeground)
4291 4301 {
4292 4302 CSaveFileStateJob job(*m_progressTrackingItem,
  4303 + *m_stackFileItemToUpdate,
4293 4304 m_progressTrackingVideoResumeBookmark,
4294 4305 m_progressTrackingPlayCountUpdate);
4295 4306
@@ -4299,6 +4310,7 @@ void CApplication::SaveFileState(bool bForeground /* = false */)
4299 4310 else
4300 4311 {
4301 4312 CJob* job = new CSaveFileStateJob(*m_progressTrackingItem,
  4313 + *m_stackFileItemToUpdate,
4302 4314 m_progressTrackingVideoResumeBookmark,
4303 4315 m_progressTrackingPlayCountUpdate);
4304 4316 CJobManager::GetInstance().AddJob(job, NULL);
2  xbmc/Application.h
@@ -370,6 +370,8 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
370 370
371 371 CFileItemPtr m_itemCurrentFile;
372 372 CFileItemList* m_currentStack;
  373 + CFileItemPtr m_stackFileItemToUpdate;
  374 +
373 375 CStdString m_prevMedia;
374 376 CSplash* m_splash;
375 377 ThreadIdentifier m_threadID; // application thread ID. Used in applicationMessanger to know where we are firing a thread with delay from.
5 xbmc/FileItem.cpp
@@ -74,6 +74,7 @@ CFileItem::CFileItem(const CSong& song)
74 74 m_strPath = song.strFileName;
75 75 GetMusicInfoTag()->SetSong(song);
76 76 m_lStartOffset = song.iStartOffset;
  77 + m_lStartPartNumber = 0;
77 78 SetProperty("item_start", song.iStartOffset);
78 79 m_lEndOffset = song.iEndOffset;
79 80 m_strThumbnailImage = song.strThumb;
@@ -297,6 +298,7 @@ const CFileItem& CFileItem::operator=(const CFileItem& item)
297 298 }
298 299
299 300 m_lStartOffset = item.m_lStartOffset;
  301 + m_lStartPartNumber = item.m_lStartPartNumber;
300 302 m_lEndOffset = item.m_lEndOffset;
301 303 m_strDVDLabel = item.m_strDVDLabel;
302 304 m_strTitle = item.m_strTitle;
@@ -333,6 +335,7 @@ void CFileItem::Reset()
333 335 m_dateTime.Reset();
334 336 m_iDriveType = CMediaSource::SOURCE_TYPE_UNKNOWN;
335 337 m_lStartOffset = 0;
  338 + m_lStartPartNumber = 0;
336 339 m_lEndOffset = 0;
337 340 m_iprogramCount = 0;
338 341 m_idepth = 1;
@@ -371,6 +374,7 @@ void CFileItem::Archive(CArchive& ar)
371 374 ar << m_iprogramCount;
372 375 ar << m_idepth;
373 376 ar << m_lStartOffset;
  377 + ar << m_lStartPartNumber;
374 378 ar << m_lEndOffset;
375 379 ar << m_iLockMode;
376 380 ar << m_strLockCode;
@@ -417,6 +421,7 @@ void CFileItem::Archive(CArchive& ar)
417 421 ar >> m_iprogramCount;
418 422 ar >> m_idepth;
419 423 ar >> m_lStartOffset;
  424 + ar >> m_lStartPartNumber;
420 425 ar >> m_lEndOffset;
421 426 int temp;
422 427 ar >> temp;
1  xbmc/FileItem.h
@@ -310,6 +310,7 @@ class CFileItem :
310 310 int m_iprogramCount;
311 311 int m_idepth;
312 312 int m_lStartOffset;
  313 + int m_lStartPartNumber;
313 314 int m_lEndOffset;
314 315 LockType m_iLockMode;
315 316 CStdString m_strLockCode;
2  xbmc/dialogs/GUIDialogContextMenu.cpp
@@ -308,7 +308,7 @@ void CGUIDialogContextMenu::GetContextButtons(const CStdString &type, const CFil
308 308 {
309 309 // We need to check if there is a detected is inserted!
310 310 buttons.Add(CONTEXT_BUTTON_PLAY_DISC, 341); // Play CD/DVD!
311   - if (CGUIWindowVideoBase::GetResumeItemOffset(item.get()) > 0)
  311 + if (CGUIWindowVideoBase::HasResumeItemOffset(item.get()))
312 312 buttons.Add(CONTEXT_BUTTON_RESUME_DISC, CGUIWindowVideoBase::GetResumeString(*(item.get()))); // Resume Disc
313 313
314 314 buttons.Add(CONTEXT_BUTTON_EJECT_DISC, 13391); // Eject/Load CD/DVD!
9 xbmc/utils/SaveFileStateJob.h
@@ -8,13 +8,16 @@
8 8 class CSaveFileStateJob : public CJob
9 9 {
10 10 CFileItem m_item;
  11 + CFileItem m_item_discstack;
11 12 CBookmark m_bookmark;
12 13 bool m_updatePlayCount;
13 14 public:
14 15 CSaveFileStateJob(const CFileItem& item,
  16 + const CFileItem& item_discstack,
15 17 const CBookmark& bookmark,
16 18 bool updatePlayCount)
17 19 : m_item(item),
  20 + m_item_discstack(item_discstack),
18 21 m_bookmark(bookmark),
19 22 m_updatePlayCount(updatePlayCount) {}
20 23 virtual ~CSaveFileStateJob() {}
@@ -85,6 +88,12 @@ bool CSaveFileStateJob::DoWork()
85 88 videodatabase.SetStreamDetailsForFile(m_item.GetVideoInfoTag()->m_streamDetails,progressTrackingFile);
86 89 updateListing = true;
87 90 }
  91 + // in order to properly update the the list, we need to update the stack item which is held in g_application.m_stackFileItemToUpdate
  92 + if (m_item.HasProperty("stackFileItemToUpdate"))
  93 + {
  94 + m_item = m_item_discstack; // as of now, the item is replaced by the discstack item
  95 + videodatabase.GetResumePoint(*m_item.GetVideoInfoTag());
  96 + }
88 97 videodatabase.Close();
89 98
90 99 if (updateListing)
1  xbmc/video/Bookmark.cpp
@@ -32,6 +32,7 @@ void CBookmark::Reset()
32 32 seasonNumber = 0;
33 33 timeInSeconds = 0.0f;
34 34 totalTimeInSeconds = 0.0f;
  35 + partNumber = 0;
35 36 type = STANDARD;
36 37 }
37 38
1  xbmc/video/Bookmark.h
@@ -31,6 +31,7 @@ class CBookmark
31 31 void Reset();
32 32 double timeInSeconds;
33 33 double totalTimeInSeconds;
  34 + long partNumber;
34 35 CStdString thumbNailImage;
35 36 CStdString playerState;
36 37 CStdString player;
111 xbmc/video/VideoDatabase.cpp
@@ -2253,41 +2253,55 @@ void CVideoDatabase::GetFilePathById(int idMovie, CStdString &filePath, VIDEODB_
2253 2253 }
2254 2254
2255 2255 //********************************************************************************************************************************
2256   -void CVideoDatabase::GetBookMarksForFile(const CStdString& strFilenameAndPath, VECBOOKMARKS& bookmarks, CBookmark::EType type /*= CBookmark::STANDARD*/, bool bAppend)
  2256 +void CVideoDatabase::GetBookMarksForFile(const CStdString& strFilenameAndPath, VECBOOKMARKS& bookmarks, CBookmark::EType type /*= CBookmark::STANDARD*/, bool bAppend, long partNumber)
2257 2257 {
2258 2258 try
2259 2259 {
2260   - int idFile = GetFileId(strFilenameAndPath);
2261   - if (idFile < 0) return ;
2262   - if (!bAppend)
2263   - bookmarks.erase(bookmarks.begin(), bookmarks.end());
2264   - if (NULL == m_pDB.get()) return ;
2265   - if (NULL == m_pDS.get()) return ;
2266   -
2267   - CStdString strSQL=PrepareSQL("select * from bookmark where idFile=%i and type=%i order by timeInSeconds", idFile, (int)type);
2268   - m_pDS->query( strSQL.c_str() );
2269   - while (!m_pDS->eof())
  2260 + if (URIUtils::IsStack(strFilenameAndPath) && CFileItem(CStackDirectory::GetFirstStackedFile(strFilenameAndPath),false).IsDVDImage())
2270 2261 {
2271   - CBookmark bookmark;
2272   - bookmark.timeInSeconds = m_pDS->fv("timeInSeconds").get_asDouble();
2273   - bookmark.totalTimeInSeconds = m_pDS->fv("totalTimeInSeconds").get_asDouble();
2274   - bookmark.thumbNailImage = m_pDS->fv("thumbNailImage").get_asString();
2275   - bookmark.playerState = m_pDS->fv("playerState").get_asString();
2276   - bookmark.player = m_pDS->fv("player").get_asString();
2277   - bookmark.type = type;
2278   - if (type == CBookmark::EPISODE)
  2262 + CStackDirectory dir;
  2263 + CFileItemList fileList;
  2264 + dir.GetDirectory(strFilenameAndPath, fileList);
  2265 + if (!bAppend)
  2266 + bookmarks.clear();
  2267 + for (int i = fileList.Size() - 1; i >= 0; i--) // put the bookmarks of the highest part first in the list
  2268 + GetBookMarksForFile(fileList[i]->GetPath(), bookmarks, type, true, (i+1));
  2269 + }
  2270 + else
  2271 + {
  2272 + int idFile = GetFileId(strFilenameAndPath);
  2273 + if (idFile < 0) return ;
  2274 + if (!bAppend)
  2275 + bookmarks.erase(bookmarks.begin(), bookmarks.end());
  2276 + if (NULL == m_pDB.get()) return ;
  2277 + if (NULL == m_pDS.get()) return ;
  2278 +
  2279 + CStdString strSQL=PrepareSQL("select * from bookmark where idFile=%i and type=%i order by timeInSeconds", idFile, (int)type);
  2280 + m_pDS->query( strSQL.c_str() );
  2281 + while (!m_pDS->eof())
2279 2282 {
2280   - CStdString strSQL2=PrepareSQL("select c%02d, c%02d from episode where c%02d=%i order by c%02d, c%02d", VIDEODB_ID_EPISODE_EPISODE, VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_EPISODE_BOOKMARK, m_pDS->fv("idBookmark").get_asInt(), VIDEODB_ID_EPISODE_SORTSEASON, VIDEODB_ID_EPISODE_SORTEPISODE);
2281   - m_pDS2->query(strSQL2.c_str());
2282   - bookmark.episodeNumber = m_pDS2->fv(0).get_asInt();
2283   - bookmark.seasonNumber = m_pDS2->fv(1).get_asInt();
2284   - m_pDS2->close();
  2283 + CBookmark bookmark;
  2284 + bookmark.timeInSeconds = m_pDS->fv("timeInSeconds").get_asDouble();
  2285 + bookmark.partNumber = partNumber;
  2286 + bookmark.totalTimeInSeconds = m_pDS->fv("totalTimeInSeconds").get_asDouble();
  2287 + bookmark.thumbNailImage = m_pDS->fv("thumbNailImage").get_asString();
  2288 + bookmark.playerState = m_pDS->fv("playerState").get_asString();
  2289 + bookmark.player = m_pDS->fv("player").get_asString();
  2290 + bookmark.type = type;
  2291 + if (type == CBookmark::EPISODE)
  2292 + {
  2293 + CStdString strSQL2=PrepareSQL("select c%02d, c%02d from episode where c%02d=%i order by c%02d, c%02d", VIDEODB_ID_EPISODE_EPISODE, VIDEODB_ID_EPISODE_SEASON, VIDEODB_ID_EPISODE_BOOKMARK, m_pDS->fv("idBookmark").get_asInt(), VIDEODB_ID_EPISODE_SORTSEASON, VIDEODB_ID_EPISODE_SORTEPISODE);
  2294 + m_pDS2->query(strSQL2.c_str());
  2295 + bookmark.episodeNumber = m_pDS2->fv(0).get_asInt();
  2296 + bookmark.seasonNumber = m_pDS2->fv(1).get_asInt();
  2297 + m_pDS2->close();
  2298 + }
  2299 + bookmarks.push_back(bookmark);
  2300 + m_pDS->next();
2285 2301 }
2286   - bookmarks.push_back(bookmark);
2287   - m_pDS->next();
  2302 + //sort(bookmarks.begin(), bookmarks.end(), SortBookmarks);
  2303 + m_pDS->close();
2288 2304 }
2289   - //sort(bookmarks.begin(), bookmarks.end(), SortBookmarks);
2290   - m_pDS->close();
2291 2305 }
2292 2306 catch (...)
2293 2307 {
@@ -2940,7 +2954,7 @@ bool CVideoDatabase::GetStreamDetails(CVideoInfoTag& tag) const
2940 2954 return retVal;
2941 2955 }
2942 2956
2943   -bool CVideoDatabase::GetResumePoint(CVideoInfoTag& tag) const
  2957 +bool CVideoDatabase::GetResumePoint(CVideoInfoTag& tag)
2944 2958 {
2945 2959 if (tag.m_iFileId < 0)
2946 2960 return false;
@@ -2949,17 +2963,38 @@ bool CVideoDatabase::GetResumePoint(CVideoInfoTag& tag) const
2949 2963
2950 2964 try
2951 2965 {
2952   - CStdString strSQL=PrepareSQL("select timeInSeconds, totalTimeInSeconds from bookmark where idFile=%i and type=%i order by timeInSeconds", tag.m_iFileId, CBookmark::RESUME);
2953   - m_pDS2->query( strSQL.c_str() );
2954   - if (!m_pDS2->eof())
  2966 + if (URIUtils::IsStack(tag.m_strFileNameAndPath) && CFileItem(CStackDirectory::GetFirstStackedFile(tag.m_strFileNameAndPath),false).IsDVDImage())
2955 2967 {
2956   - tag.m_resumePoint.timeInSeconds = m_pDS2->fv(0).get_asDouble();
2957   - tag.m_resumePoint.totalTimeInSeconds = m_pDS2->fv(1).get_asDouble();
2958   - tag.m_resumePoint.type = CBookmark::RESUME;
2959   -
2960   - match = true;
  2968 + CStackDirectory dir;
  2969 + CFileItemList fileList;
  2970 + dir.GetDirectory(tag.m_strFileNameAndPath, fileList);
  2971 + tag.m_resumePoint.Reset();
  2972 + for (int i = fileList.Size() - 1; i >= 0; i--)
  2973 + {
  2974 + CBookmark bookmark;
  2975 + if (GetResumeBookMark(fileList[i]->GetPath(), bookmark))
  2976 + {
  2977 + tag.m_resumePoint = bookmark;
  2978 + tag.m_resumePoint.partNumber = (i+1); /* store part number in here */
  2979 + match = true;
  2980 + break;
  2981 + }
  2982 + }
  2983 + }
  2984 + else
  2985 + {
  2986 + CStdString strSQL=PrepareSQL("select timeInSeconds, totalTimeInSeconds from bookmark where idFile=%i and type=%i order by timeInSeconds", tag.m_iFileId, CBookmark::RESUME);
  2987 + m_pDS2->query( strSQL.c_str() );
  2988 + if (!m_pDS2->eof())
  2989 + {
  2990 + tag.m_resumePoint.timeInSeconds = m_pDS2->fv(0).get_asDouble();
  2991 + tag.m_resumePoint.totalTimeInSeconds = m_pDS2->fv(1).get_asDouble();
  2992 + tag.m_resumePoint.partNumber = 0; // regular files or non-iso stacks don't need partNumber
  2993 + tag.m_resumePoint.type = CBookmark::RESUME;
  2994 + match = true;
  2995 + }
  2996 + m_pDS2->close();
2961 2997 }
2962   - m_pDS2->close();
2963 2998 }
2964 2999 catch (...)
2965 3000 {
4 xbmc/video/VideoDatabase.h
@@ -463,7 +463,7 @@ class CVideoDatabase : public CDatabase
463 463 bool GetStackTimes(const CStdString &filePath, std::vector<int> &times);
464 464 void SetStackTimes(const CStdString &filePath, std::vector<int> &times);
465 465
466   - void GetBookMarksForFile(const CStdString& strFilenameAndPath, VECBOOKMARKS& bookmarks, CBookmark::EType type = CBookmark::STANDARD, bool bAppend=false);
  466 + void GetBookMarksForFile(const CStdString& strFilenameAndPath, VECBOOKMARKS& bookmarks, CBookmark::EType type = CBookmark::STANDARD, bool bAppend=false, long partNumber=0);
467 467 void AddBookMarkToFile(const CStdString& strFilenameAndPath, const CBookmark &bookmark, CBookmark::EType type = CBookmark::STANDARD);
468 468 bool GetResumeBookMark(const CStdString& strFilenameAndPath, CBookmark &bookmark);
469 469 void DeleteResumeBookMark(const CStdString &strFilenameAndPath);
@@ -472,7 +472,7 @@ class CVideoDatabase : public CDatabase
472 472 bool GetBookMarkForEpisode(const CVideoInfoTag& tag, CBookmark& bookmark);
473 473 void AddBookMarkForEpisode(const CVideoInfoTag& tag, const CBookmark& bookmark);
474 474 void DeleteBookMarkForEpisode(const CVideoInfoTag& tag);
475   - bool GetResumePoint(CVideoInfoTag& tag) const;
  475 + bool GetResumePoint(CVideoInfoTag& tag);
476 476
477 477 // scraper settings
478 478 void SetScraperForPath(const CStdString& filePath, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings);
69 xbmc/video/windows/GUIWindowVideoBase.cpp
@@ -816,20 +816,22 @@ void CGUIWindowVideoBase::AddItemToPlayList(const CFileItemPtr &pItem, CFileItem
816 816 }
817 817 }
818 818
819   -int CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item)
  819 +void CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item, int& startoffset, int& partNumber)
820 820 {
821 821 // do not resume livetv
822 822 if (item->IsLiveTV())
823   - return 0;
  823 + return;
824 824
825   - CVideoDatabase db;
826   - db.Open();
827   - long startoffset = 0;
  825 + startoffset = 0;
  826 + partNumber = 0;
828 827
829 828 if (!item->IsNFO() && !item->IsPlayList())
830 829 {
831 830 if (item->HasVideoInfoTag() && item->GetVideoInfoTag()->m_resumePoint.timeInSeconds > 0.0)
832   - startoffset = (long)(item->GetVideoInfoTag()->m_resumePoint.timeInSeconds*75);
  831 + {
  832 + startoffset = (int)(item->GetVideoInfoTag()->m_resumePoint.timeInSeconds*75);
  833 + partNumber = item->GetVideoInfoTag()->m_resumePoint.partNumber;
  834 + }
833 835 else
834 836 {
835 837 CBookmark bookmark;
@@ -837,32 +839,27 @@ int CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item)
837 839 if ((item->IsVideoDb() || item->IsDVD()) && item->HasVideoInfoTag())
838 840 strPath = item->GetVideoInfoTag()->m_strFileNameAndPath;
839 841
  842 + CVideoDatabase db;
  843 + if (!db.Open())
  844 + {
  845 + CLog::Log(LOGERROR, "%s - Cannot open VideoDatabase", __FUNCTION__);
  846 + return;
  847 + }
840 848 if (db.GetResumeBookMark(strPath, bookmark))
841   - startoffset = (long)(bookmark.timeInSeconds*75);
842   -
843   - if (URIUtils::IsStack(strPath) && CFileItem(CStackDirectory::GetFirstStackedFile(strPath),false).IsDVDImage())
844 849 {
845   - CStackDirectory dir;
846   - CFileItemList movies;
847   - dir.GetDirectory(strPath, movies);
848   -
849   - /* check if any of the stacked files have a resume bookmark */
850   - for (int i = 0; i < movies.Size(); i++)
851   - {
852   - CBookmark bookmark;
853   - if (db.GetResumeBookMark(movies[i]->GetPath(), bookmark))
854   - {
855   - startoffset = (long)(bookmark.timeInSeconds);
856   - startoffset += 0x10000000 * (i+1); /* store file number in here */
857   - // don't break, we take the last one!
858   - }
859   - }
  850 + startoffset = (int)(bookmark.timeInSeconds*75);
  851 + partNumber = bookmark.partNumber;
860 852 }
  853 + db.Close();
861 854 }
862 855 }
863   - db.Close();
  856 +}
864 857
865   - return startoffset;
  858 +bool CGUIWindowVideoBase::HasResumeItemOffset(const CFileItem *item)
  859 +{
  860 + int startoffset, partNumber = 0;
  861 + GetResumeItemOffset(item, startoffset, partNumber);
  862 + return startoffset > 0;
866 863 }
867 864
868 865 bool CGUIWindowVideoBase::OnClick(int iItem)
@@ -1017,20 +1014,15 @@ CStdString CGUIWindowVideoBase::GetResumeString(CFileItem item)
1017 1014 if (item.IsVideoDb() || item.IsDVD())
1018 1015 itemPath = item.GetVideoInfoTag()->m_strFileNameAndPath;
1019 1016
1020   - if (URIUtils::IsStack(itemPath) && CFileItem(CStackDirectory::GetFirstStackedFile(itemPath),false).IsDVDImage())
  1017 + if (db.GetResumeBookMark(itemPath, bookmark))
1021 1018 {
1022   - int startoffset = GetResumeItemOffset(&item);
1023   - if (startoffset > 0)
  1019 + resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(bookmark.timeInSeconds)).c_str());
  1020 + if (bookmark.partNumber > 0)
1024 1021 {
1025   - int selectedPart = (startoffset>>28);
1026   - startoffset = startoffset & ~0xF0000000;
1027   - partString.Format(g_localizeStrings.Get(23051).c_str(), selectedPart);
1028   - resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(startoffset)).c_str());
  1022 + partString.Format(g_localizeStrings.Get(23051).c_str(), bookmark.partNumber);
1029 1023 resumeString.append(" (").append(partString).append(")");
1030 1024 }
1031 1025 }
1032   - else if (db.GetResumeBookMark(itemPath, bookmark) )
1033   - resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(bookmark.timeInSeconds)).c_str());
1034 1026 db.Close();
1035 1027 }
1036 1028 return resumeString;
@@ -1233,7 +1225,7 @@ void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &but
1233 1225 // if autoresume is enabled then add restart video button
1234 1226 // check to see if the Resume Video button is applicable
1235 1227 // only if the video is NOT a DVD (in that case the resume button will be added by CGUIDialogContextMenu::GetContextButtons)
1236   - if (!item->IsDVD() && GetResumeItemOffset(item.get()) > 0)
  1228 + if (!item->IsDVD() && HasResumeItemOffset(item.get()))
1237 1229 {
1238 1230 buttons.Add(CONTEXT_BUTTON_RESUME_ITEM, GetResumeString(*(item.get()))); // Resume Video
1239 1231 }
@@ -1280,7 +1272,7 @@ bool CGUIWindowVideoBase::OnPlayStackPart(int iItem)
1280 1272 if (CFileItem(CStackDirectory::GetFirstStackedFile(path),false).IsDVDImage())
1281 1273 {
1282 1274 CStdString resumeString = CGUIWindowVideoBase::GetResumeString(*(parts[selectedFile - 1].get()));
1283   - stack->m_lStartOffset = 0x10000000 * (selectedFile); /* store file number in here */
  1275 + stack->m_lStartOffset = 0;
1284 1276 if (!resumeString.IsEmpty())
1285 1277 {
1286 1278 CContextButtons choices;
@@ -1288,10 +1280,11 @@ bool CGUIWindowVideoBase::OnPlayStackPart(int iItem)
1288 1280 choices.Add(SELECT_ACTION_PLAY, 12021); // Start from beginning
1289 1281 int value = CGUIDialogContextMenu::ShowAndGetChoice(choices);
1290 1282 if (value == SELECT_ACTION_RESUME)
1291   - stack->m_lStartOffset += (long)CGUIWindowVideoBase::GetResumeItemOffset(parts[selectedFile - 1].get());
  1283 + GetResumeItemOffset(parts[selectedFile - 1].get(), stack->m_lStartOffset, stack->m_lStartPartNumber);
1292 1284 else if (value != SELECT_ACTION_PLAY)
1293 1285 return false; // if not selected PLAY, then we changed our mind so return
1294 1286 }
  1287 + stack->m_lStartPartNumber = selectedFile;
1295 1288 }
1296 1289 // regular stack
1297 1290 else
3  xbmc/video/windows/GUIWindowVideoBase.h
@@ -35,7 +35,8 @@ class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObse
35 35 virtual bool OnAction(const CAction &action);
36 36
37 37 void PlayMovie(const CFileItem *item);
38   - static int GetResumeItemOffset(const CFileItem *item);
  38 + static void GetResumeItemOffset(const CFileItem *item, int& startoffset, int& partNumber);
  39 + static bool HasResumeItemOffset(const CFileItem *item);
39 40
40 41 void AddToDatabase(int iItem);
41 42 virtual void OnInfo(CFileItem* pItem, const ADDON::ScraperPtr& scraper);

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.