2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "GUIDialogVideoBookmarks.h"
23 #include "video/VideoDatabase.h"
24 #include "Application.h"
25 #ifdef HAS_VIDEO_PLAYBACK
26 #include "cores/VideoRenderers/RenderManager.h"
27 #include "cores/VideoRenderers/RenderCapture.h"
29 #include "pictures/Picture.h"
30 #include "dialogs/GUIDialogContextMenu.h"
31 #include "view/ViewState.h"
32 #include "profiles/ProfilesManager.h"
33 #include "dialogs/GUIDialogKaiToast.h"
34 #include "settings/AdvancedSettings.h"
36 #include "guilib/Texture.h"
37 #include "guilib/GUIWindowManager.h"
38 #include "utils/Crc32.h"
39 #include "guilib/Key.h"
40 #include "guilib/LocalizeStrings.h"
41 #include "utils/StringUtils.h"
42 #include "utils/URIUtils.h"
43 #include "threads/SingleLock.h"
44 #include "utils/log.h"
45 #include "utils/Variant.h"
47 #include "cores/IPlayer.h"
51 #define BOOKMARK_THUMB_WIDTH g_advancedSettings.GetThumbSize()
53 #define CONTROL_ADD_BOOKMARK 2
54 #define CONTROL_CLEAR_BOOKMARKS 3
55 #define CONTROL_ADD_EPISODE_BOOKMARK 4
57 #define CONTROL_LIST 10
58 #define CONTROL_THUMBS 11
60 CGUIDialogVideoBookmarks::CGUIDialogVideoBookmarks()
61 : CGUIDialog(WINDOW_DIALOG_VIDEO_BOOKMARKS, "VideoOSDBookmarks.xml")
63 m_vecItems = new CFileItemList;
64 m_loadType = KEEP_IN_MEMORY;
67 CGUIDialogVideoBookmarks::~CGUIDialogVideoBookmarks()
72 bool CGUIDialogVideoBookmarks::OnMessage(CGUIMessage& message)
74 switch ( message.GetMessage() )
76 case GUI_MSG_WINDOW_DEINIT:
78 CUtil::DeleteVideoDatabaseDirectoryCache();
83 case GUI_MSG_WINDOW_INIT:
85 CGUIWindow::OnMessage(message);
93 int iControl = message.GetSenderId();
94 if (iControl == CONTROL_ADD_BOOKMARK)
99 else if (iControl == CONTROL_CLEAR_BOOKMARKS)
103 else if (iControl == CONTROL_ADD_EPISODE_BOOKMARK)
105 AddEpisodeBookmark();
108 else if (m_viewControl.HasControl(iControl)) // list/thumb control
110 int iItem = m_viewControl.GetSelectedItem();
111 int iAction = message.GetParam1();
112 if (iAction == ACTION_DELETE_ITEM)
116 else if (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK)
123 case GUI_MSG_SETFOCUS:
125 if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId())
127 m_viewControl.SetFocused();
132 case GUI_MSG_REFRESH_LIST:
139 return CGUIDialog::OnMessage(message);
142 bool CGUIDialogVideoBookmarks::OnAction(const CAction &action)
144 switch(action.GetID())
146 case ACTION_CONTEXT_MENU:
147 case ACTION_MOUSE_RIGHT_CLICK:
149 OnPopupMenu(m_viewControl.GetSelectedItem());
153 return CGUIDialog::OnAction(action);
157 void CGUIDialogVideoBookmarks::OnPopupMenu(int item)
159 if (item < 0 || item >= m_vecItems->Size())
162 // highlight the item
163 (*m_vecItems)[item]->Select(true);
165 CContextButtons choices;
167 int langID = 20404; //"Remove bookmark"
168 if (m_bookmarks[item].type == CBookmark::EPISODE)
169 langID = 20405; //"Remove episode bookmark"
170 choices.Add(1, langID);
173 int button = CGUIDialogContextMenu::ShowAndGetChoice(choices);
175 // unhighlight the item
176 (*m_vecItems)[item]->Select(false);
182 void CGUIDialogVideoBookmarks::Delete(int item)
184 if ( item>=0 && (unsigned)item < m_bookmarks.size() )
186 CVideoDatabase videoDatabase;
187 videoDatabase.Open();
188 videoDatabase.ClearBookMarkOfFile(g_application.CurrentFile(),m_bookmarks[item],m_bookmarks[item].type);
189 videoDatabase.Close();
190 CUtil::DeleteVideoDatabaseDirectoryCache();
195 void CGUIDialogVideoBookmarks::OnRefreshList()
198 CBookmark resumemark;
200 // open the d/b and retrieve the bookmarks for the current movie
201 CStdString path = g_application.CurrentFile();
202 if (g_application.CurrentFileItem().HasProperty("original_listitem_url") &&
203 !URIUtils::IsVideoDb(g_application.CurrentFileItem().GetProperty("original_listitem_url").asString()))
204 path = g_application.CurrentFileItem().GetProperty("original_listitem_url").asString();
205 CVideoDatabase videoDatabase;
206 videoDatabase.Open();
207 videoDatabase.GetBookMarksForFile(path, m_bookmarks);
208 videoDatabase.GetBookMarksForFile(path, m_bookmarks, CBookmark::EPISODE, true);
209 /* push in the resume mark first */
210 if( videoDatabase.GetResumeBookMark(path, resumemark) )
211 m_bookmarks.push_back(resumemark);
213 videoDatabase.Close();
215 // cycle through each stored bookmark and add it to our list control
216 for (unsigned int i = 0; i < m_bookmarks.size(); ++i)
218 if (m_bookmarks[i].type == CBookmark::RESUME)
219 m_bookmarks[i].thumbNailImage = "bookmark-resume.png";
221 CStdString bookmarkTime;
222 if (m_bookmarks[i].type == CBookmark::EPISODE)
223 bookmarkTime.Format("%s %i %s %i", g_localizeStrings.Get(20373), m_bookmarks[i].seasonNumber, g_localizeStrings.Get(20359).c_str(), m_bookmarks[i].episodeNumber);
225 bookmarkTime = StringUtils::SecondsToTimeString((long)m_bookmarks[i].timeInSeconds, TIME_FORMAT_HH_MM_SS);
227 CFileItemPtr item(new CFileItem(bookmarkTime));
228 item->SetArt("thumb", m_bookmarks[i].thumbNailImage);
229 m_vecItems->Add(item);
231 m_viewControl.SetItems(*m_vecItems);
234 void CGUIDialogVideoBookmarks::Update()
236 CVideoDatabase videoDatabase;
237 videoDatabase.Open();
239 if (g_application.CurrentFileItem().HasVideoInfoTag() && g_application.CurrentFileItem().GetVideoInfoTag()->m_iEpisode > -1)
241 vector<CVideoInfoTag> episodes;
242 videoDatabase.GetEpisodesByFile(g_application.CurrentFile(),episodes);
243 if (episodes.size() > 1)
245 CONTROL_ENABLE(CONTROL_ADD_EPISODE_BOOKMARK);
249 CONTROL_DISABLE(CONTROL_ADD_EPISODE_BOOKMARK);
254 CONTROL_DISABLE(CONTROL_ADD_EPISODE_BOOKMARK);
258 // lock our display, as this window is rendered from the player thread
259 g_graphicsContext.Lock();
260 m_viewControl.SetCurrentView(DEFAULT_VIEW_ICONS);
262 // empty the list ready for population
267 g_graphicsContext.Unlock();
269 videoDatabase.Close();
272 void CGUIDialogVideoBookmarks::Clear()
274 m_viewControl.Clear();
278 void CGUIDialogVideoBookmarks::GotoBookmark(int item)
280 if (item < 0 || item >= (int)m_bookmarks.size()) return;
281 if (g_application.m_pPlayer->HasPlayer())
283 g_application.m_pPlayer->SetPlayerState(m_bookmarks[item].playerState);
284 g_application.SeekTime((double)m_bookmarks[item].timeInSeconds);
288 void CGUIDialogVideoBookmarks::ClearBookmarks()
290 CVideoDatabase videoDatabase;
291 videoDatabase.Open();
292 CStdString path = g_application.CurrentFile();
293 if (g_application.CurrentFileItem().HasProperty("original_listitem_url") &&
294 !URIUtils::IsVideoDb(g_application.CurrentFileItem().GetProperty("original_listitem_url").asString()))
295 path = g_application.CurrentFileItem().GetProperty("original_listitem_url").asString();
296 videoDatabase.ClearBookMarksOfFile(path, CBookmark::STANDARD);
297 videoDatabase.ClearBookMarksOfFile(path, CBookmark::RESUME);
298 videoDatabase.ClearBookMarksOfFile(path, CBookmark::EPISODE);
299 videoDatabase.Close();
303 bool CGUIDialogVideoBookmarks::AddBookmark(CVideoInfoTag* tag)
305 CVideoDatabase videoDatabase;
307 bookmark.timeInSeconds = (int)g_application.GetTime();
308 bookmark.totalTimeInSeconds = (int)g_application.GetTotalTime();
310 if( g_application.m_pPlayer->HasPlayer() )
311 bookmark.playerState = g_application.m_pPlayer->GetPlayerState();
313 bookmark.playerState.Empty();
315 bookmark.player = CPlayerCoreFactory::Get().GetPlayerName(g_application.GetCurrentPlayer());
317 // create the thumbnail image
318 #ifdef HAS_VIDEO_PLAYBACK
319 float aspectRatio = g_renderManager.GetAspectRatio();
321 float aspectRatio = 1.0f;
323 int width = BOOKMARK_THUMB_WIDTH;
324 int height = (int)(BOOKMARK_THUMB_WIDTH / aspectRatio);
325 if (height > (int)BOOKMARK_THUMB_WIDTH)
327 height = BOOKMARK_THUMB_WIDTH;
328 width = (int)(BOOKMARK_THUMB_WIDTH * aspectRatio);
331 #ifdef HAS_VIDEO_PLAYBACK
332 CRenderCapture* thumbnail = g_renderManager.AllocRenderCapture();
336 g_renderManager.Capture(thumbnail, width, height, CAPTUREFLAG_IMMEDIATELY);
338 if (thumbnail->GetUserState() == CAPTURESTATE_DONE)
341 crc.ComputeFromLowerCase(g_application.CurrentFile());
342 bookmark.thumbNailImage.Format("%08x_%i.jpg", (unsigned __int32) crc, (int)bookmark.timeInSeconds);
343 bookmark.thumbNailImage = URIUtils::AddFileToFolder(CProfilesManager::Get().GetBookmarksThumbFolder(), bookmark.thumbNailImage);
344 if (!CPicture::CreateThumbnailFromSurface(thumbnail->GetPixels(), width, height, thumbnail->GetWidth() * 4,
345 bookmark.thumbNailImage))
346 bookmark.thumbNailImage.Empty();
349 CLog::Log(LOGERROR,"CGUIDialogVideoBookmarks: failed to create thumbnail");
351 g_renderManager.ReleaseRenderCapture(thumbnail);
355 videoDatabase.Open();
357 videoDatabase.AddBookMarkForEpisode(*tag, bookmark);
360 CStdString path = g_application.CurrentFile();
361 if (g_application.CurrentFileItem().HasProperty("original_listitem_url") &&
362 !URIUtils::IsVideoDb(g_application.CurrentFileItem().GetProperty("original_listitem_url").asString()))
363 path = g_application.CurrentFileItem().GetProperty("original_listitem_url").asString();
364 videoDatabase.AddBookMarkToFile(path, bookmark, CBookmark::STANDARD);
366 videoDatabase.Close();
370 void CGUIDialogVideoBookmarks::OnWindowLoaded()
372 CGUIDialog::OnWindowLoaded();
373 m_viewControl.Reset();
374 m_viewControl.SetParentWindow(GetID());
375 m_viewControl.AddView(GetControl(CONTROL_THUMBS));
378 void CGUIDialogVideoBookmarks::OnWindowUnload()
380 CGUIDialog::OnWindowUnload();
381 m_viewControl.Reset();
384 CGUIControl *CGUIDialogVideoBookmarks::GetFirstFocusableControl(int id)
386 if (m_viewControl.HasControl(id))
387 id = m_viewControl.GetCurrentControl();
388 return CGUIWindow::GetFirstFocusableControl(id);
391 bool CGUIDialogVideoBookmarks::AddEpisodeBookmark()
393 vector<CVideoInfoTag> episodes;
394 CVideoDatabase videoDatabase;
395 videoDatabase.Open();
396 videoDatabase.GetEpisodesByFile(g_application.CurrentFile(), episodes);
397 videoDatabase.Close();
398 if(episodes.size() > 0)
400 CContextButtons choices;
401 for (unsigned int i=0; i < episodes.size(); ++i)
403 CStdString strButton;
404 strButton.Format("%s %i, %s %i", g_localizeStrings.Get(20373), episodes[i].m_iSeason, g_localizeStrings.Get(20359).c_str(), episodes[i].m_iEpisode);
405 choices.Add(i, strButton);
408 int pressed = CGUIDialogContextMenu::ShowAndGetChoice(choices);
411 AddBookmark(&episodes[pressed]);
420 bool CGUIDialogVideoBookmarks::OnAddBookmark()
422 if (!g_application.CurrentFileItem().IsVideo())
425 if (CGUIDialogVideoBookmarks::AddBookmark())
427 g_windowManager.SendMessage(GUI_MSG_REFRESH_LIST, 0, WINDOW_DIALOG_VIDEO_BOOKMARKS);
428 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info,
429 g_localizeStrings.Get(298), //"Bookmarks"
430 g_localizeStrings.Get(21362));//"Bookmark created"
436 bool CGUIDialogVideoBookmarks::OnAddEpisodeBookmark()
438 bool bReturn = false;
439 if (g_application.CurrentFileItem().HasVideoInfoTag() && g_application.CurrentFileItem().GetVideoInfoTag()->m_iEpisode > -1)
441 CVideoDatabase videoDatabase;
442 videoDatabase.Open();
443 vector<CVideoInfoTag> episodes;
444 videoDatabase.GetEpisodesByFile(g_application.CurrentFile(),episodes);
445 if (episodes.size() > 1)
447 bReturn = CGUIDialogVideoBookmarks::AddEpisodeBookmark();
450 g_windowManager.SendMessage(GUI_MSG_REFRESH_LIST, 0, WINDOW_DIALOG_VIDEO_BOOKMARKS);
451 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info,
452 g_localizeStrings.Get(298), //"Bookmarks"
453 g_localizeStrings.Get(21363));//"Episode Bookmark created"
457 videoDatabase.Close();