LinuxRendererGLES.h: correct path to `DVDVideoCodec.h`
[vuplus_xbmc] / xbmc / video / windows / GUIWindowVideoBase.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "system.h"
23 #include "GUIWindowVideoBase.h"
24 #include "Util.h"
25 #include "video/VideoInfoDownloader.h"
26 #include "utils/RegExp.h"
27 #include "utils/Variant.h"
28 #include "addons/AddonManager.h"
29 #include "addons/IAddon.h"
30 #include "video/dialogs/GUIDialogVideoInfo.h"
31 #include "GUIWindowVideoNav.h"
32 #include "dialogs/GUIDialogFileBrowser.h"
33 #include "video/dialogs/GUIDialogVideoScan.h"
34 #include "dialogs/GUIDialogSmartPlaylistEditor.h"
35 #include "dialogs/GUIDialogProgress.h"
36 #include "dialogs/GUIDialogYesNo.h"
37 #include "playlists/PlayListFactory.h"
38 #include "Application.h"
39 #include "NfoFile.h"
40 #include "PlayListPlayer.h"
41 #include "GUIPassword.h"
42 #include "filesystem/ZipManager.h"
43 #include "filesystem/StackDirectory.h"
44 #include "filesystem/MultiPathDirectory.h"
45 #include "video/dialogs/GUIDialogFileStacking.h"
46 #include "dialogs/GUIDialogMediaSource.h"
47 #include "windows/GUIWindowFileManager.h"
48 #include "filesystem/VideoDatabaseDirectory.h"
49 #include "PartyModeManager.h"
50 #include "guilib/GUIWindowManager.h"
51 #include "dialogs/GUIDialogOK.h"
52 #include "dialogs/GUIDialogSelect.h"
53 #include "dialogs/GUIDialogKeyboard.h"
54 #include "filesystem/Directory.h"
55 #include "playlists/PlayList.h"
56 #include "settings/Settings.h"
57 #include "settings/AdvancedSettings.h"
58 #include "settings/GUISettings.h"
59 #include "settings/GUIDialogContentSettings.h"
60 #include "guilib/LocalizeStrings.h"
61 #include "utils/StringUtils.h"
62 #include "utils/log.h"
63 #include "utils/FileUtils.h"
64 #include "utils/URIUtils.h"
65
66 #include "addons/Skin.h"
67
68 using namespace std;
69 using namespace XFILE;
70 using namespace PLAYLIST;
71 using namespace VIDEODATABASEDIRECTORY;
72 using namespace VIDEO;
73 using namespace ADDON;
74
75 #define CONTROL_BTNVIEWASICONS     2
76 #define CONTROL_BTNSORTBY          3
77 #define CONTROL_BTNSORTASC         4
78 #define CONTROL_BTNTYPE            5
79 #define CONTROL_LABELFILES        12
80
81 #define CONTROL_PLAY_DVD           6
82 #define CONTROL_STACK              7
83 #define CONTROL_BTNSCAN            8
84
85 CGUIWindowVideoBase::CGUIWindowVideoBase(int id, const CStdString &xmlFile)
86     : CGUIMediaWindow(id, xmlFile)
87 {
88   m_thumbLoader.SetObserver(this);
89   m_thumbLoader.SetStreamDetailsObserver(this);
90   m_stackingAvailable = true;
91 }
92
93 CGUIWindowVideoBase::~CGUIWindowVideoBase()
94 {
95 }
96
97 bool CGUIWindowVideoBase::OnAction(const CAction &action)
98 {
99   if (action.GetID() == ACTION_SHOW_PLAYLIST)
100   {
101     OutputDebugString("activate guiwindowvideoplaylist!\n");
102     g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
103     return true;
104   }
105   if (action.GetID() == ACTION_SCAN_ITEM)
106     return OnContextButton(m_viewControl.GetSelectedItem(),CONTEXT_BUTTON_SCAN);
107
108   return CGUIMediaWindow::OnAction(action);
109 }
110
111 bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
112 {
113   switch ( message.GetMessage() )
114   {
115   case GUI_MSG_WINDOW_DEINIT:
116     if (m_thumbLoader.IsLoading())
117       m_thumbLoader.StopThread();
118     m_database.Close();
119     break;
120
121   case GUI_MSG_WINDOW_INIT:
122     {
123       m_database.Open();
124
125       m_dlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
126
127       // save current window, unless the current window is the video playlist window
128       if (GetID() != WINDOW_VIDEO_PLAYLIST && g_settings.m_iVideoStartWindow != GetID())
129       {
130         g_settings.m_iVideoStartWindow = GetID();
131         g_settings.Save();
132       }
133
134       return CGUIMediaWindow::OnMessage(message);
135     }
136     break;
137
138   case GUI_MSG_CLICKED:
139     {
140       int iControl = message.GetSenderId();
141       if (iControl == CONTROL_STACK)
142       {
143         g_settings.m_videoStacking = !g_settings.m_videoStacking;
144         g_settings.Save();
145         UpdateButtons();
146         Update( m_vecItems->m_strPath );
147       }
148       else if (iControl == CONTROL_PLAY_DVD)
149       {
150         // play movie...
151         CUtil::PlayDVD();
152       }
153       else if (iControl == CONTROL_BTNTYPE)
154       {
155         CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_BTNTYPE);
156         g_windowManager.SendMessage(msg);
157
158         int nSelected = msg.GetParam1();
159         int nNewWindow = WINDOW_VIDEO_FILES;
160         switch (nSelected)
161         {
162         case 0:  // Movies
163           nNewWindow = WINDOW_VIDEO_FILES;
164           break;
165         case 1:  // Library
166           nNewWindow = WINDOW_VIDEO_NAV;
167           break;
168         }
169
170         if (nNewWindow != GetID())
171         {
172           g_settings.m_iVideoStartWindow = nNewWindow;
173           g_settings.Save();
174           g_windowManager.ChangeActiveWindow(nNewWindow);
175           CGUIMessage msg2(GUI_MSG_SETFOCUS, nNewWindow, CONTROL_BTNTYPE);
176           g_windowManager.SendMessage(msg2);
177         }
178
179         return true;
180       }
181       else if (m_viewControl.HasControl(iControl))  // list/thumb control
182       {
183         // get selected item
184         int iItem = m_viewControl.GetSelectedItem();
185         int iAction = message.GetParam1();
186
187         // iItem is checked for validity inside these routines
188         if (iAction == ACTION_QUEUE_ITEM || iAction == ACTION_MOUSE_MIDDLE_CLICK)
189         {
190           OnQueueItem(iItem);
191           return true;
192         }
193         else if (iAction == ACTION_SHOW_INFO)
194         {
195           return OnInfo(iItem);
196         }
197         else if (iAction == ACTION_PLAYER_PLAY && !g_application.IsPlayingVideo())
198         {
199           return OnResumeItem(iItem);
200         }
201         else if (iAction == ACTION_DELETE_ITEM)
202         {
203           // is delete allowed?
204           if (g_settings.GetCurrentProfile().canWriteDatabases())
205           {
206             // must be at the title window
207             if (GetID() == WINDOW_VIDEO_NAV)
208               OnDeleteItem(iItem);
209
210             // or be at the files window and have file deletion enabled
211             else if (GetID() == WINDOW_VIDEO_FILES && g_guiSettings.GetBool("filelists.allowfiledeletion"))
212               OnDeleteItem(iItem);
213
214             // or be at the video playlists location
215             else if (m_vecItems->m_strPath.Equals("special://videoplaylists/"))
216               OnDeleteItem(iItem);
217             else
218               return false;
219
220             return true;
221           }
222         }
223       }
224     }
225     break;
226   }
227   return CGUIMediaWindow::OnMessage(message);
228 }
229
230 void CGUIWindowVideoBase::UpdateButtons()
231 {
232   // Remove labels from the window selection
233   CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_BTNTYPE);
234   g_windowManager.SendMessage(msg);
235
236   // Add labels to the window selection
237   CStdString strItem = g_localizeStrings.Get(744); // Files
238   CGUIMessage msg2(GUI_MSG_LABEL_ADD, GetID(), CONTROL_BTNTYPE);
239   msg2.SetLabel(strItem);
240   g_windowManager.SendMessage(msg2);
241
242   strItem = g_localizeStrings.Get(14022); // Library
243   msg2.SetLabel(strItem);
244   g_windowManager.SendMessage(msg2);
245
246   // Select the current window as default item
247   int nWindow = g_settings.m_iVideoStartWindow-WINDOW_VIDEO_FILES;
248   CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, nWindow);
249
250   CONTROL_ENABLE(CONTROL_BTNSCAN);
251
252   SET_CONTROL_LABEL(CONTROL_STACK, 14000);  // Stack
253   SET_CONTROL_SELECTED(GetID(), CONTROL_STACK, g_settings.m_videoStacking);
254   CONTROL_ENABLE_ON_CONDITION(CONTROL_STACK, m_stackingAvailable);
255   
256   CGUIMediaWindow::UpdateButtons();
257 }
258
259 void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const ADDON::ScraperPtr& scraper)
260 {
261   if (!pItem)
262     return;
263
264   if (pItem->IsParentFolder() || pItem->m_bIsShareOrDrive || pItem->m_strPath.Equals("add"))
265     return;
266
267   // ShowIMDB can kill the item as this window can be closed while we do it,
268   // so take a copy of the item now
269   CFileItem item(*pItem);
270   if (item.IsVideoDb() && item.HasVideoInfoTag())
271   {
272     if (item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty())
273       item.m_strPath = item.GetVideoInfoTag()->m_strPath;
274     else
275       item.m_strPath = item.GetVideoInfoTag()->m_strFileNameAndPath;
276   }
277   else
278   {
279     if (item.m_bIsFolder && scraper && scraper->Content() != CONTENT_TVSHOWS)
280     {
281       CFileItemList items;
282       CDirectory::GetDirectory(item.m_strPath, items,"",true,false,DIR_CACHE_ONCE,true,true);
283       items.Stack();
284
285       // check for media files
286       bool bFoundFile(false);
287       for (int i = 0; i < items.Size(); ++i)
288       {
289         CFileItemPtr item2 = items[i];
290
291         if (item2->IsVideo() && !item2->IsPlayList() &&
292             !CUtil::ExcludeFileOrFolder(item2->m_strPath, g_advancedSettings.m_moviesExcludeFromScanRegExps))
293         {
294           item.m_strPath = item2->m_strPath;
295           item.m_bIsFolder = false;
296           bFoundFile = true;
297           break;
298         }
299       }
300
301       // no video file in this folder
302       if (!bFoundFile)
303       {
304         CGUIDialogOK::ShowAndGetInput(13346,20349,20022,20022);
305         return;
306       }
307     }
308   }
309
310   // we need to also request any thumbs be applied to the folder item
311   if (pItem->m_bIsFolder)
312     item.SetProperty("set_folder_thumb", pItem->m_strPath);
313
314   bool modified = ShowIMDB(&item, scraper);
315   if (modified &&
316      (g_windowManager.GetActiveWindow() == WINDOW_VIDEO_FILES ||
317       g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV)) // since we can be called from the music library we need this check
318   {
319     int itemNumber = m_viewControl.GetSelectedItem();
320     Update(m_vecItems->m_strPath);
321     m_viewControl.SetSelectedItem(itemNumber);
322   }
323 }
324
325 // ShowIMDB is called as follows:
326 // 1.  To lookup info on a file.
327 // 2.  To lookup info on a folder (which may or may not contain a file)
328 // 3.  To lookup info just for fun (no file or folder related)
329
330 // We just need the item object for this.
331 // A "blank" item object is sent for 3.
332 // If a folder is sent, currently it sets strFolder and bFolder
333 // this is only used for setting the folder thumb, however.
334
335 // Steps should be:
336
337 // 1.  Check database to see if we have this information already
338 // 2.  Else, check for a nfoFile to get the URL
339 // 3.  Run a loop to check for refresh
340 // 4.  If no URL is present do a search to get the URL
341 // 4.  Once we have the URL, download the details
342 // 5.  Once we have the details, add to the database if necessary (case 1,2)
343 //     and show the information.
344 // 6.  Check for a refresh, and if so, go to 3.
345
346 bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const ScraperPtr &info2)
347 {
348   /*
349   CLog::Log(LOGDEBUG,"CGUIWindowVideoBase::ShowIMDB");
350   CLog::Log(LOGDEBUG,"  strMovie  = [%s]", strMovie.c_str());
351   CLog::Log(LOGDEBUG,"  strFile   = [%s]", strFile.c_str());
352   CLog::Log(LOGDEBUG,"  strFolder = [%s]", strFolder.c_str());
353   CLog::Log(LOGDEBUG,"  bFolder   = [%s]", ((int)bFolder ? "true" : "false"));
354   */
355
356   CGUIDialogProgress* pDlgProgress = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS);
357   CGUIDialogSelect* pDlgSelect = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
358   CGUIDialogVideoInfo* pDlgInfo = (CGUIDialogVideoInfo*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_INFO);
359
360   ScraperPtr info(info2); // use this as nfo might change it..
361
362   if (!pDlgProgress) return false;
363   if (!pDlgSelect) return false;
364   if (!pDlgInfo) return false;
365
366   // 1.  Check for already downloaded information, and if we have it, display our dialog
367   //     Return if no Refresh is needed.
368   bool bHasInfo=false;
369
370   CVideoInfoTag movieDetails;
371   movieDetails.Reset();
372   if (info)
373   {
374     m_database.Open(); // since we can be called from the music library
375
376     if (info->Content() == CONTENT_MOVIES)
377     {
378       if (m_database.HasMovieInfo(item->m_strPath))
379       {
380         bHasInfo = true;
381         m_database.GetMovieInfo(item->m_strPath, movieDetails);
382       }
383     }
384     if (info->Content() == CONTENT_TVSHOWS)
385     {
386       if (item->m_bIsFolder)
387       {
388         if (m_database.HasTvShowInfo(item->m_strPath))
389         {
390           bHasInfo = true;
391           m_database.GetTvShowInfo(item->m_strPath, movieDetails);
392         }
393       }
394       else
395       {
396         int EpisodeHint=-1;
397         if (item->HasVideoInfoTag())
398           EpisodeHint = item->GetVideoInfoTag()->m_iEpisode;
399         int idEpisode=-1;
400         if ((idEpisode = m_database.GetEpisodeId(item->m_strPath,EpisodeHint)) > -1)
401         {
402           bHasInfo = true;
403           m_database.GetEpisodeInfo(item->m_strPath, movieDetails, idEpisode);
404         }
405         else
406         {
407           // !! WORKAROUND !!
408           // As we cannot add an episode to a non-existing tvshow entry, we have to check the parent directory
409           // to see if it`s already in our video database. If it's not yet part of the database we will exit here.
410           // (Ticket #4764)
411           //
412           // NOTE: This will fail for episodes on multipath shares, as the parent path isn't what is stored in the
413           //       database.  Possible solutions are to store the paths in the db separately and rely on the show
414           //       stacking stuff, or to modify GetTvShowId to do support multipath:// shares
415           CStdString strParentDirectory;
416           URIUtils::GetParentPath(item->m_strPath, strParentDirectory);
417           if (m_database.GetTvShowId(strParentDirectory) < 0)
418           {
419             CLog::Log(LOGERROR,"%s: could not add episode [%s]. tvshow does not exist yet..", __FUNCTION__, item->m_strPath.c_str());
420             return false;
421           }
422         }
423       }
424     }
425     if (info->Content() == CONTENT_MUSICVIDEOS)
426     {
427       if (m_database.HasMusicVideoInfo(item->m_strPath))
428       {
429         bHasInfo = true;
430         m_database.GetMusicVideoInfo(item->m_strPath, movieDetails);
431       }
432     }
433     m_database.Close();
434   }
435   else if(item->HasVideoInfoTag())
436   {
437     bHasInfo = true;
438     movieDetails = *item->GetVideoInfoTag();
439   }
440   
441   bool needsRefresh = false;
442   if (bHasInfo)
443   {
444     if (!info || info->Content() == CONTENT_NONE) // disable refresh button
445       movieDetails.m_strIMDBNumber = "xx"+movieDetails.m_strIMDBNumber;
446     *item->GetVideoInfoTag() = movieDetails;
447     pDlgInfo->SetMovie(item);
448     pDlgInfo->DoModal();
449     needsRefresh = pDlgInfo->NeedRefresh();
450     if (!needsRefresh)
451       return pDlgInfo->HasUpdatedThumb();
452   }
453
454   // quietly return if Internet lookups are disabled
455   if (!g_settings.GetCurrentProfile().canWriteDatabases() && !g_passwordManager.bMasterUser)
456     return false;
457
458   if(!info)
459     return false;
460
461   CGUIDialogVideoScan* pDialog = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
462   if (pDialog && pDialog->IsScanning())
463   {
464     CGUIDialogOK::ShowAndGetInput(13346,14057,-1,-1);
465     return false;
466   }
467
468   m_database.Open();
469   // 2. Look for a nfo File to get the search URL
470   SScanSettings settings;
471   info = m_database.GetScraperForPath(item->m_strPath,settings);
472
473   if (!info)
474     return false;
475
476   // Get the correct movie title
477   CStdString movieName = item->GetMovieName(settings.parent_name);
478
479   CScraperUrl scrUrl;
480   CVideoInfoScanner scanner;
481   bool hasDetails = false;
482   bool listNeedsUpdating = false;
483   bool ignoreNfo = false;
484   // 3. Run a loop so that if we Refresh we re-run this block
485   do
486   {
487     if (!ignoreNfo)
488     {
489       CNfoFile::NFOResult nfoResult = scanner.CheckForNFOFile(item,settings.parent_name_root,info,scrUrl);
490       if (nfoResult == CNfoFile::ERROR_NFO)
491         ignoreNfo = true;
492       else
493       if (nfoResult != CNfoFile::NO_NFO)
494         hasDetails = true;
495
496       if (needsRefresh)
497       {
498         bHasInfo = true;
499         if (nfoResult == CNfoFile::URL_NFO || nfoResult == CNfoFile::COMBINED_NFO || nfoResult == CNfoFile::FULL_NFO)
500         {
501           if (CGUIDialogYesNo::ShowAndGetInput(13346,20446,20447,20022))
502           {
503             hasDetails = false;
504             ignoreNfo = true;
505             scrUrl.Clear();
506             info = info2;
507           }
508         }
509       }
510     }
511
512     // 4. if we don't have an url, or need to refresh the search
513     //    then do the web search
514     MOVIELIST movielist;
515     if (info->Content() == CONTENT_TVSHOWS && !item->m_bIsFolder)
516       hasDetails = true;
517
518     if (!hasDetails && (scrUrl.m_url.size() == 0 || needsRefresh))
519     {
520       // 4a. show dialog that we're busy querying www.imdb.com
521       CStdString strHeading;
522       strHeading.Format(g_localizeStrings.Get(197),info->Name().c_str());
523       pDlgProgress->SetHeading(strHeading);
524       pDlgProgress->SetLine(0, movieName);
525       pDlgProgress->SetLine(1, "");
526       pDlgProgress->SetLine(2, "");
527       pDlgProgress->StartModal();
528       pDlgProgress->Progress();
529
530       // 4b. do the websearch
531       info->ClearCache();
532       CVideoInfoDownloader imdb(info);
533       int returncode = imdb.FindMovie(movieName, movielist, pDlgProgress);
534       if (returncode > 0)
535       {
536         pDlgProgress->Close();
537         if (movielist.size() > 0)
538         {
539           int iString = 196;
540           if (info->Content() == CONTENT_TVSHOWS)
541             iString = 20356;
542           pDlgSelect->SetHeading(iString);
543           pDlgSelect->Reset();
544           for (unsigned int i = 0; i < movielist.size(); ++i)
545             pDlgSelect->Add(movielist[i].strTitle);
546           pDlgSelect->EnableButton(true, 413); // manual
547           pDlgSelect->DoModal();
548
549           // and wait till user selects one
550           int iSelectedMovie = pDlgSelect->GetSelectedLabel();
551           if (iSelectedMovie >= 0)
552           {
553             scrUrl = movielist[iSelectedMovie];
554             CLog::Log(LOGDEBUG, "%s: user selected movie '%s' with URL '%s'",
555               __FUNCTION__, scrUrl.strTitle.c_str(), scrUrl.m_url[0].m_url.c_str());
556           }
557           else if (!pDlgSelect->IsButtonPressed())
558           {
559             m_database.Close();
560             return listNeedsUpdating; // user backed out
561           }
562         }
563       }
564       else if (returncode == -1 || !CVideoInfoScanner::DownloadFailed(pDlgProgress))
565       {
566         pDlgProgress->Close();
567         return false;
568       }
569     }
570     // 4c. Check if url is still empty - occurs if user has selected to do a manual
571     //     lookup, or if the IMDb lookup failed or was cancelled.
572     if (!hasDetails && scrUrl.m_url.size() == 0)
573     {
574       // Check for cancel of the progress dialog
575       pDlgProgress->Close();
576       if (pDlgProgress->IsCanceled())
577       {
578         m_database.Close();
579         return listNeedsUpdating;
580       }
581
582       // Prompt the user to input the movieName
583       int iString = 16009;
584       if (info->Content() == CONTENT_TVSHOWS)
585         iString = 20357;
586       if (!CGUIDialogKeyboard::ShowAndGetInput(movieName, g_localizeStrings.Get(iString), false))
587       {
588         m_database.Close();
589         return listNeedsUpdating; // user backed out
590       }
591
592       needsRefresh = true;
593     }
594     else
595     {
596       // 5. Download the movie information
597       // show dialog that we're downloading the movie info
598       CFileItemList list;
599       CStdString strPath=item->m_strPath;
600       if (item->IsVideoDb())
601       {
602         CFileItemPtr newItem(new CFileItem(*item->GetVideoInfoTag()));
603         list.Add(newItem);
604         strPath = item->GetVideoInfoTag()->m_strPath;
605       }
606       else
607       {
608         CFileItemPtr newItem(new CFileItem(*item));
609         list.Add(newItem);
610       }
611
612       if (item->m_bIsFolder)
613         URIUtils::GetParentPath(strPath,list.m_strPath);
614       else
615         URIUtils::GetDirectory(strPath,list.m_strPath);
616
617       int iString=198;
618       if (info->Content() == CONTENT_TVSHOWS)
619       {
620         if (item->m_bIsFolder)
621           iString = 20353;
622         else
623           iString = 20361;
624       }
625       if (info->Content() == CONTENT_MUSICVIDEOS)
626         iString = 20394;
627       pDlgProgress->SetHeading(iString);
628       pDlgProgress->SetLine(0, movieName);
629       pDlgProgress->SetLine(1, scrUrl.strTitle);
630       pDlgProgress->SetLine(2, "");
631       pDlgProgress->StartModal();
632       pDlgProgress->Progress();
633       if (bHasInfo)
634       {
635         if (info->Content() == CONTENT_MOVIES)
636           m_database.DeleteMovie(item->m_strPath);
637         if (info->Content() == CONTENT_TVSHOWS && !item->m_bIsFolder)
638           m_database.DeleteEpisode(item->m_strPath,movieDetails.m_iDbId);
639         if (info->Content() == CONTENT_MUSICVIDEOS)
640           m_database.DeleteMusicVideo(item->m_strPath);
641         if (info->Content() == CONTENT_TVSHOWS && item->m_bIsFolder)
642         {
643           if (pDlgInfo->RefreshAll())
644             m_database.DeleteTvShow(item->m_strPath);
645           else
646             m_database.DeleteDetailsForTvShow(item->m_strPath);
647         }
648       }
649       if (scanner.RetrieveVideoInfo(list,settings.parent_name_root,info->Content(),!ignoreNfo,&scrUrl,pDlgInfo->RefreshAll(),pDlgProgress))
650       {
651         if (info->Content() == CONTENT_MOVIES)
652           m_database.GetMovieInfo(item->m_strPath,movieDetails);
653         if (info->Content() == CONTENT_MUSICVIDEOS)
654           m_database.GetMusicVideoInfo(item->m_strPath,movieDetails);
655         if (info->Content() == CONTENT_TVSHOWS)
656         {
657           // update tvshow info to get updated episode numbers
658           if (item->m_bIsFolder)
659             m_database.GetTvShowInfo(item->m_strPath,movieDetails);
660           else
661             m_database.GetEpisodeInfo(item->m_strPath,movieDetails);
662         }
663
664         // got all movie details :-)
665         OutputDebugString("got details\n");
666         pDlgProgress->Close();
667
668         // now show the imdb info
669         OutputDebugString("show info\n");
670
671         // remove directory caches and reload images
672         CUtil::DeleteVideoDatabaseDirectoryCache();
673         CGUIMessage reload(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS);
674         OnMessage(reload);
675
676         *item->GetVideoInfoTag() = movieDetails;
677         pDlgInfo->SetMovie(item);
678         pDlgInfo->DoModal();
679         item->SetThumbnailImage(pDlgInfo->GetThumbnail());
680         needsRefresh = pDlgInfo->NeedRefresh();
681         listNeedsUpdating = true;
682       }
683       else
684       {
685         pDlgProgress->Close();
686         if (pDlgProgress->IsCanceled())
687         {
688           m_database.Close();
689           return listNeedsUpdating; // user cancelled
690         }
691         CGUIDialogOK::ShowAndGetInput(195, movieName, 0, 0);
692         m_database.Close();
693         return listNeedsUpdating;
694       }
695     }
696   // 6. Check for a refresh
697   } while (needsRefresh);
698   m_database.Close();
699   return listNeedsUpdating;
700 }
701
702 void CGUIWindowVideoBase::OnQueueItem(int iItem)
703 {
704   if ( iItem < 0 || iItem >= m_vecItems->Size() ) return ;
705
706   // we take a copy so that we can alter the queue state
707   CFileItemPtr item(new CFileItem(*m_vecItems->Get(iItem)));
708   if (item->IsRAR() || item->IsZIP())
709     return;
710
711   //  Allow queuing of unqueueable items
712   //  when we try to queue them directly
713   if (!item->CanQueue())
714     item->SetCanQueue(true);
715
716   CFileItemList queuedItems;
717   AddItemToPlayList(item, queuedItems);
718   // if party mode, add items but DONT start playing
719   if (g_partyModeManager.IsEnabled(PARTYMODECONTEXT_VIDEO))
720   {
721     g_partyModeManager.AddUserSongs(queuedItems, false);
722     return;
723   }
724
725   g_playlistPlayer.Add(PLAYLIST_VIDEO, queuedItems);
726   // video does not auto play on queue like music
727   m_viewControl.SetSelectedItem(iItem + 1);
728 }
729
730 void CGUIWindowVideoBase::AddItemToPlayList(const CFileItemPtr &pItem, CFileItemList &queuedItems)
731 {
732   if (!pItem->CanQueue() || pItem->IsRAR() || pItem->IsZIP() || pItem->IsParentFolder()) // no zip/rar enques thank you!
733     return;
734
735   if (pItem->m_bIsFolder)
736   {
737     if (pItem->IsParentFolder())
738       return;
739
740     // Check if we add a locked share
741     if ( pItem->m_bIsShareOrDrive )
742     {
743       CFileItem item = *pItem;
744       if ( !g_passwordManager.IsItemUnlocked( &item, "video" ) )
745         return;
746     }
747
748     // recursive
749     CFileItemList items;
750     GetDirectory(pItem->m_strPath, items);
751     FormatAndSort(items);
752
753     int watchedMode = g_settings.GetWatchMode(m_vecItems->GetContent());
754     bool unwatchedOnly = watchedMode == VIDEO_SHOW_UNWATCHED;
755     bool watchedOnly = watchedMode == VIDEO_SHOW_WATCHED;
756     for (int i = 0; i < items.Size(); ++i)
757     {
758       if (items[i]->m_bIsFolder)
759       {
760         CStdString strPath = items[i]->m_strPath;
761         URIUtils::RemoveSlashAtEnd(strPath);
762         strPath.ToLower();
763         if (strPath.size() > 6)
764         {
765           CStdString strSub = strPath.substr(strPath.size()-6);
766           if (strPath.Mid(strPath.size()-6).Equals("sample")) // skip sample folders
767             continue;
768         }
769       }
770       else if (items[i]->HasVideoInfoTag() &&
771        ((unwatchedOnly && items[i]->GetVideoInfoTag()->m_playCount > 0) ||
772         (watchedOnly && items[i]->GetVideoInfoTag()->m_playCount <= 0)))
773         continue;
774
775       AddItemToPlayList(items[i], queuedItems);
776     }
777   }
778   else
779   {
780     // just an item
781     if (pItem->IsPlayList())
782     {
783       auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(*pItem));
784       if (pPlayList.get())
785       {
786         // load it
787         if (!pPlayList->Load(pItem->m_strPath))
788         {
789           CGUIDialogOK::ShowAndGetInput(6, 0, 477, 0);
790           return; //hmmm unable to load playlist?
791         }
792
793         CPlayList playlist = *pPlayList;
794         for (int i = 0; i < (int)playlist.size(); ++i)
795         {
796           AddItemToPlayList(playlist[i], queuedItems);
797         }
798         return;
799       }
800     }
801     else if(pItem->IsInternetStream())
802     { // just queue the internet stream, it will be expanded on play
803       queuedItems.Add(pItem);
804     }
805     else if (pItem->IsPlugin() && pItem->GetProperty("isplayable") == "true")
806     { // a playable python files
807       queuedItems.Add(pItem);
808     }
809     else if (pItem->IsVideoDb())
810     { // this case is needed unless we allow IsVideo() to return true for videodb items,
811       // but then we have issues with playlists of videodb items
812       CFileItemPtr item(new CFileItem(*pItem->GetVideoInfoTag()));
813       queuedItems.Add(item);
814     }
815     else if (!pItem->IsNFO() && pItem->IsVideo())
816     {
817       queuedItems.Add(pItem);
818     }
819   }
820 }
821
822 int  CGUIWindowVideoBase::GetResumeItemOffset(const CFileItem *item)
823 {
824   // do not resume livetv
825   if (item->IsLiveTV())
826     return 0;
827
828   CVideoDatabase db;
829   db.Open();
830   long startoffset = 0;
831
832   if (item->IsStack() && (!g_guiSettings.GetBool("myvideos.treatstackasfile") ||
833                           CFileItem(CStackDirectory::GetFirstStackedFile(item->m_strPath),false).IsDVDImage()) )
834   {
835
836     CStdStringArray movies;
837     GetStackedFiles(item->m_strPath, movies);
838
839     /* check if any of the stacked files have a resume bookmark */
840     for (unsigned i = 0; i<movies.size();i++)
841     {
842       CBookmark bookmark;
843       if (db.GetResumeBookMark(movies[i], bookmark))
844       {
845         startoffset = (long)(bookmark.timeInSeconds*75);
846         startoffset += 0x10000000 * (i+1); /* store file number in here */
847         break;
848       }
849     }
850   }
851   else if (!item->IsNFO() && !item->IsPlayList())
852   {
853     CBookmark bookmark;
854     CStdString strPath = item->m_strPath;
855     if (item->IsVideoDb() && item->HasVideoInfoTag())
856       strPath = item->GetVideoInfoTag()->m_strFileNameAndPath;
857
858     if (db.GetResumeBookMark(strPath, bookmark))
859       startoffset = (long)(bookmark.timeInSeconds*75);
860   }
861   db.Close();
862
863   return startoffset;
864 }
865
866 bool CGUIWindowVideoBase::OnClick(int iItem)
867 {
868   return CGUIMediaWindow::OnClick(iItem);
869 }
870
871 bool CGUIWindowVideoBase::OnSelect(int iItem)
872 {
873   if (iItem < 0 || iItem >= m_vecItems->Size())
874     return false;
875
876   CFileItemPtr item = m_vecItems->Get(iItem);
877
878   if (!item->m_bIsFolder && item->m_strPath != "add")
879     return OnFileAction(iItem, g_guiSettings.GetInt("myvideos.selectaction"));
880
881   return CGUIMediaWindow::OnSelect(iItem);
882 }
883
884 bool CGUIWindowVideoBase::OnFileAction(int iItem, int action)
885 {
886   CFileItemPtr item = m_vecItems->Get(iItem);
887   
888   switch (action)
889   {
890   case SELECT_ACTION_CHOOSE:
891     {
892       CContextButtons choices;
893       bool resume = false;
894
895       if (!item->IsLiveTV())
896       {
897         CStdString resumeString = GetResumeString(*item);
898         if (!resumeString.IsEmpty()) 
899         {
900           resume = true;
901           choices.Add(SELECT_ACTION_RESUME, resumeString);
902           choices.Add(SELECT_ACTION_PLAY, 12021);   // Start from beginning
903         }
904       }
905       if (!resume)
906         choices.Add(SELECT_ACTION_PLAY, 208);   // Play
907
908       choices.Add(SELECT_ACTION_INFO, 22081); // Info
909       choices.Add(SELECT_ACTION_MORE, 22082); // More
910       int value = CGUIDialogContextMenu::ShowAndGetChoice(choices);
911       if (value < 0)
912         return true;
913
914       return OnFileAction(iItem, value);
915     }
916     break;
917   case SELECT_ACTION_PLAY_OR_RESUME:
918     return OnResumeItem(iItem);
919   case SELECT_ACTION_INFO:
920     if (OnInfo(iItem))
921       return true;
922     break;
923   case SELECT_ACTION_MORE:
924     OnPopupMenu(iItem);
925     return true;
926   case SELECT_ACTION_RESUME:
927     item->m_lStartOffset = STARTOFFSET_RESUME;
928     break;
929   case SELECT_ACTION_PLAY:
930   default:
931     break;
932   }
933   return OnClick(iItem);
934 }
935
936 bool CGUIWindowVideoBase::OnInfo(int iItem) 
937 {
938   if (iItem < 0 || iItem >= m_vecItems->Size())
939     return false;
940
941   CFileItemPtr item = m_vecItems->Get(iItem);
942
943   if (item->m_strPath.Equals("add") || item->IsParentFolder())
944     return false;
945
946   ADDON::ScraperPtr scraper;
947   if (!m_vecItems->IsPlugin() && !m_vecItems->IsRSS() && !m_vecItems->IsLiveTV())
948   {
949     CStdString strDir;
950     if (item->IsVideoDb()       &&
951         item->HasVideoInfoTag() &&
952         !item->GetVideoInfoTag()->m_strPath.IsEmpty())
953     {
954       strDir = item->GetVideoInfoTag()->m_strPath;
955     }
956     else
957       URIUtils::GetDirectory(item->m_strPath,strDir);
958
959     SScanSettings settings;
960     bool foundDirectly = false;
961     scraper = m_database.GetScraperForPath(strDir, settings, foundDirectly);
962
963     if (!scraper &&
964         !(m_database.HasMovieInfo(item->m_strPath) ||
965           m_database.HasTvShowInfo(strDir)           ||
966           m_database.HasEpisodeInfo(item->m_strPath)))
967     {
968       return false;
969     }
970
971     if (scraper && scraper->Content() == CONTENT_TVSHOWS && foundDirectly && !settings.parent_name_root) // dont lookup on root tvshow folder
972       return true;
973   }
974
975   OnInfo(item.get(), scraper);
976
977   return true;
978 }
979
980 void CGUIWindowVideoBase::OnRestartItem(int iItem)
981 {
982   CGUIMediaWindow::OnClick(iItem);
983 }
984
985 CStdString CGUIWindowVideoBase::GetResumeString(CFileItem item) 
986 {
987   CStdString resumeString;
988   CVideoDatabase db;
989   if (db.Open())
990   {
991     CBookmark bookmark;
992     CStdString itemPath(item.m_strPath);
993     if (item.IsVideoDb())
994       itemPath = item.GetVideoInfoTag()->m_strFileNameAndPath;
995     if (db.GetResumeBookMark(itemPath, bookmark) )
996       resumeString.Format(g_localizeStrings.Get(12022).c_str(), StringUtils::SecondsToTimeString(lrint(bookmark.timeInSeconds)).c_str());
997     db.Close();
998   }
999   return resumeString;
1000 }
1001
1002 bool CGUIWindowVideoBase::ShowResumeMenu(CFileItem &item)
1003 {
1004   if (!item.m_bIsFolder && !item.IsLiveTV())
1005   {
1006     CStdString resumeString = GetResumeString(item);
1007     if (!resumeString.IsEmpty())
1008     { // prompt user whether they wish to resume
1009       CContextButtons choices;
1010       choices.Add(1, resumeString);
1011       choices.Add(2, 12021); // start from the beginning
1012       int retVal = CGUIDialogContextMenu::ShowAndGetChoice(choices);
1013       if (retVal < 0)
1014         return false; // don't do anything
1015       if (retVal == 1)
1016         item.m_lStartOffset = STARTOFFSET_RESUME;
1017     }
1018   }
1019   return true;
1020 }
1021
1022 bool CGUIWindowVideoBase::OnResumeItem(int iItem)
1023 {
1024   if (iItem < 0 || iItem >= m_vecItems->Size()) return true;
1025   CFileItemPtr item = m_vecItems->Get(iItem);
1026
1027   if (!item->m_bIsFolder)
1028   {
1029     CStdString resumeString = GetResumeString(*item);
1030     if (!resumeString.IsEmpty())
1031     {
1032       CContextButtons choices;
1033       choices.Add(SELECT_ACTION_RESUME, resumeString);
1034       choices.Add(SELECT_ACTION_PLAY, 12021);   // Start from beginning
1035       int value = CGUIDialogContextMenu::ShowAndGetChoice(choices);
1036       if (value < 0)
1037         return true;
1038       return OnFileAction(iItem, value);
1039     }
1040   }
1041
1042   return OnFileAction(iItem, SELECT_ACTION_PLAY);
1043 }
1044
1045 void CGUIWindowVideoBase::OnStreamDetails(const CStreamDetails &details, const CStdString &strFileName, long lFileId)
1046 {
1047   CVideoDatabase db;
1048   if (db.Open())
1049   {
1050     if (lFileId < 0)
1051       db.SetStreamDetailsForFile(details, strFileName);
1052     else
1053       db.SetStreamDetailsForFileId(details, lFileId);
1054
1055     db.Close();
1056   }
1057 }
1058
1059 void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &buttons)
1060 {
1061   CFileItemPtr item;
1062   if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
1063     item = m_vecItems->Get(itemNumber);
1064
1065   // contextual buttons
1066   if (item && !item->GetPropertyBOOL("pluginreplacecontextitems"))
1067   {
1068     if (!item->IsParentFolder())
1069     {
1070       CStdString path(item->m_strPath);
1071       if (item->IsVideoDb() && item->HasVideoInfoTag())
1072         path = item->GetVideoInfoTag()->m_strFileNameAndPath;
1073
1074       if (!item->IsPlugin() && !item->IsAddonsPath() && !item->IsLiveTV())
1075       {
1076         if (URIUtils::IsStack(path))
1077         {
1078           vector<int> times;
1079           if (m_database.GetStackTimes(path,times))
1080             buttons.Add(CONTEXT_BUTTON_PLAY_PART, 20324);
1081         }
1082
1083         if (!m_vecItems->m_strPath.IsEmpty() && !item->m_strPath.Left(19).Equals("newsmartplaylist://")
1084             && !m_vecItems->m_strPath.Left(10).Equals("sources://"))
1085         {
1086           buttons.Add(CONTEXT_BUTTON_QUEUE_ITEM, 13347);      // Add to Playlist
1087         }
1088
1089         // allow a folder to be ad-hoc queued and played by the default player
1090         if (item->m_bIsFolder || (item->IsPlayList() &&
1091            !g_advancedSettings.m_playlistAsFolders))
1092         {
1093           buttons.Add(CONTEXT_BUTTON_PLAY_ITEM, 208);
1094         }
1095       }
1096       if (!item->m_bIsFolder && !(item->IsPlayList() && !g_advancedSettings.m_playlistAsFolders))
1097       { // get players
1098         VECPLAYERCORES vecCores;
1099         if (item->IsVideoDb())
1100         {
1101           CFileItem item2;
1102           item2.m_strPath = item->GetVideoInfoTag()->m_strFileNameAndPath;
1103           CPlayerCoreFactory::GetPlayers(item2, vecCores);
1104         }
1105         else
1106           CPlayerCoreFactory::GetPlayers(*item, vecCores);
1107         if (vecCores.size() > 1)
1108           buttons.Add(CONTEXT_BUTTON_PLAY_WITH, 15213);
1109       }
1110       if (item->IsSmartPlayList())
1111       {
1112         buttons.Add(CONTEXT_BUTTON_PLAY_PARTYMODE, 15216); // Play in Partymode
1113       }
1114
1115       // if autoresume is enabled then add restart video button
1116       // check to see if the Resume Video button is applicable
1117       if (GetResumeItemOffset(item.get()) > 0)
1118       {
1119         buttons.Add(CONTEXT_BUTTON_RESUME_ITEM, GetResumeString(*(item.get())));     // Resume Video
1120       }
1121       if (item->HasVideoInfoTag() && !item->m_bIsFolder && item->GetVideoInfoTag()->m_iEpisode > -1)
1122       {
1123         buttons.Add(CONTEXT_BUTTON_PLAY_AND_QUEUE, 13412);
1124       }
1125       if (item->IsSmartPlayList() || m_vecItems->IsSmartPlayList())
1126         buttons.Add(CONTEXT_BUTTON_EDIT_SMART_PLAYLIST, 586);
1127     }
1128   }
1129   CGUIMediaWindow::GetContextButtons(itemNumber, buttons);
1130 }
1131
1132 void CGUIWindowVideoBase::GetNonContextButtons(int itemNumber, CContextButtons &buttons)
1133 {
1134   if (g_playlistPlayer.GetPlaylist(PLAYLIST_VIDEO).size() > 0)
1135     buttons.Add(CONTEXT_BUTTON_NOW_PLAYING, 13350);
1136 }
1137
1138 bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
1139 {
1140   CFileItemPtr item;
1141   if (itemNumber >= 0 && itemNumber < m_vecItems->Size())
1142     item = m_vecItems->Get(itemNumber);
1143   switch (button)
1144   {
1145   case CONTEXT_BUTTON_SET_CONTENT:
1146     {
1147       SScanSettings settings;
1148       ADDON::ScraperPtr info = m_database.GetScraperForPath(item->HasVideoInfoTag() ? item->GetVideoInfoTag()->m_strPath : item->m_strPath, settings);
1149       OnAssignContent(item->m_strPath,0, info, settings);
1150       return true;
1151     }
1152   case CONTEXT_BUTTON_PLAY_PART:
1153     {
1154       CFileItemList items;
1155       CStdString path(item->m_strPath);
1156       if (item->IsVideoDb())
1157         path = item->GetVideoInfoTag()->m_strFileNameAndPath;
1158
1159       CDirectory::GetDirectory(path,items);
1160       CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)g_windowManager.GetWindow(WINDOW_DIALOG_FILESTACKING);
1161       if (!dlg) return true;
1162       dlg->SetNumberOfFiles(items.Size());
1163       dlg->DoModal();
1164       int btn2 = dlg->GetSelectedFile();
1165       if (btn2 > 0)
1166       {
1167         if (btn2 > 1)
1168         {
1169           vector<int> times;
1170           if (m_database.GetStackTimes(path,times))
1171             item->m_lStartOffset = times[btn2-2]*75; // wtf?
1172         }
1173         else
1174           item->m_lStartOffset = 0;
1175
1176         // call CGUIMediaWindow::OnClick() as otherwise autoresume will kick in
1177         CGUIMediaWindow::OnClick(itemNumber);
1178       }
1179       return true;
1180     }
1181   case CONTEXT_BUTTON_QUEUE_ITEM:
1182     OnQueueItem(itemNumber);
1183     return true;
1184
1185   case CONTEXT_BUTTON_PLAY_ITEM:
1186     PlayItem(itemNumber);
1187     return true;
1188
1189   case CONTEXT_BUTTON_PLAY_WITH:
1190     {
1191       VECPLAYERCORES vecCores;
1192       if (item->IsVideoDb())
1193       {
1194         CFileItem item2(*item->GetVideoInfoTag());
1195         CPlayerCoreFactory::GetPlayers(item2, vecCores);
1196       }
1197       else
1198         CPlayerCoreFactory::GetPlayers(*item, vecCores);
1199       g_application.m_eForcedNextPlayer = CPlayerCoreFactory::SelectPlayerDialog(vecCores);
1200       if (g_application.m_eForcedNextPlayer != EPC_NONE)
1201         OnClick(itemNumber);
1202       return true;
1203     }
1204
1205   case CONTEXT_BUTTON_PLAY_PARTYMODE:
1206     g_partyModeManager.Enable(PARTYMODECONTEXT_VIDEO, m_vecItems->Get(itemNumber)->m_strPath);
1207     return true;
1208
1209   case CONTEXT_BUTTON_RESTART_ITEM:
1210     OnRestartItem(itemNumber);
1211     return true;
1212
1213   case CONTEXT_BUTTON_RESUME_ITEM:
1214     return OnFileAction(itemNumber, SELECT_ACTION_RESUME);
1215
1216   case CONTEXT_BUTTON_NOW_PLAYING:
1217     g_windowManager.ActivateWindow(WINDOW_VIDEO_PLAYLIST);
1218     return true;
1219
1220   case CONTEXT_BUTTON_INFO:
1221     {
1222       ADDON::ScraperPtr info;
1223       VIDEO::SScanSettings settings;
1224       GetScraperForItem(item.get(), info, settings);
1225
1226       OnInfo(item.get(),info);
1227       return true;
1228     }
1229   case CONTEXT_BUTTON_STOP_SCANNING:
1230     {
1231       CGUIDialogVideoScan *pScanDlg = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1232       if (pScanDlg && pScanDlg->IsScanning())
1233         pScanDlg->StopScanning();
1234       return true;
1235     }
1236   case CONTEXT_BUTTON_SCAN:
1237   case CONTEXT_BUTTON_UPDATE_TVSHOW:
1238     {
1239       if( !item)
1240         return false;
1241       ADDON::ScraperPtr info;
1242       SScanSettings settings;
1243       GetScraperForItem(item.get(), info, settings);
1244       CStdString strPath = item->m_strPath;
1245       if (item->IsVideoDb() && (!item->m_bIsFolder || item->GetVideoInfoTag()->m_strPath.IsEmpty()))
1246         return false;
1247
1248       if (item->IsVideoDb())
1249         strPath = item->GetVideoInfoTag()->m_strPath;
1250
1251       if (!info || info->Content() == CONTENT_NONE)
1252         return false;
1253
1254       if (item->m_bIsFolder)
1255       {
1256         m_database.SetPathHash(strPath,""); // to force scan
1257         OnScan(strPath);
1258       }
1259       else
1260         OnInfo(item.get(),info);
1261
1262       return true;
1263     }
1264   case CONTEXT_BUTTON_DELETE:
1265     OnDeleteItem(itemNumber);
1266     return true;
1267   case CONTEXT_BUTTON_EDIT_SMART_PLAYLIST:
1268     {
1269       CStdString playlist = m_vecItems->Get(itemNumber)->IsSmartPlayList() ? m_vecItems->Get(itemNumber)->m_strPath : m_vecItems->m_strPath; // save path as activatewindow will destroy our items
1270       if (CGUIDialogSmartPlaylistEditor::EditPlaylist(playlist, "video"))
1271       { // need to update
1272         m_vecItems->RemoveDiscCache(GetID());
1273         Update(m_vecItems->m_strPath);
1274       }
1275       return true;
1276     }
1277   case CONTEXT_BUTTON_RENAME:
1278     OnRenameItem(itemNumber);
1279     return true;
1280   case CONTEXT_BUTTON_MARK_WATCHED:
1281     {
1282       int newSelection = m_viewControl.GetSelectedItem() + 1;
1283       MarkWatched(item,true);
1284       m_viewControl.SetSelectedItem(newSelection);
1285
1286       CUtil::DeleteVideoDatabaseDirectoryCache();
1287       Update(m_vecItems->m_strPath);
1288       return true;
1289     }
1290   case CONTEXT_BUTTON_MARK_UNWATCHED:
1291     MarkWatched(item,false);
1292     CUtil::DeleteVideoDatabaseDirectoryCache();
1293     Update(m_vecItems->m_strPath);
1294     return true;
1295   case CONTEXT_BUTTON_PLAY_AND_QUEUE:
1296     return OnPlayAndQueueMedia(item);
1297   default:
1298     break;
1299   }
1300   return CGUIMediaWindow::OnContextButton(itemNumber, button);
1301 }
1302
1303 void CGUIWindowVideoBase::GetStackedFiles(const CStdString &strFilePath1, vector<CStdString> &movies)
1304 {
1305   CStdString strFilePath = strFilePath1;  // we're gonna be altering it
1306
1307   movies.clear();
1308
1309   CURL url(strFilePath);
1310   if (url.GetProtocol() == "stack")
1311   {
1312     CStackDirectory dir;
1313     CFileItemList items;
1314     dir.GetDirectory(strFilePath, items);
1315     for (int i = 0; i < items.Size(); ++i)
1316       movies.push_back(items[i]->m_strPath);
1317   }
1318   if (movies.empty())
1319     movies.push_back(strFilePath);
1320 }
1321
1322 bool CGUIWindowVideoBase::OnPlayMedia(int iItem)
1323 {
1324   if ( iItem < 0 || iItem >= (int)m_vecItems->Size() )
1325     return false;
1326
1327   CFileItemPtr pItem = m_vecItems->Get(iItem);
1328
1329   // party mode
1330   if (g_partyModeManager.IsEnabled(PARTYMODECONTEXT_VIDEO))
1331   {
1332     CPlayList playlistTemp;
1333     playlistTemp.Add(pItem);
1334     g_partyModeManager.AddUserSongs(playlistTemp, true);
1335     return true;
1336   }
1337
1338   // Reset Playlistplayer, playback started now does
1339   // not use the playlistplayer.
1340   g_playlistPlayer.Reset();
1341   g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_NONE);
1342
1343   CFileItem item(*pItem);
1344   if (pItem->IsVideoDb())
1345   {
1346     item.m_strPath = pItem->GetVideoInfoTag()->m_strFileNameAndPath;
1347     item.SetProperty("original_listitem_url", pItem->m_strPath);
1348   }
1349
1350   PlayMovie(&item);
1351
1352   return true;
1353 }
1354
1355 bool CGUIWindowVideoBase::OnPlayAndQueueMedia(const CFileItemPtr &item)
1356 {
1357   // Get the current playlist and make sure it is not shuffled
1358   int iPlaylist = m_guiState->GetPlaylist();
1359   if (iPlaylist != PLAYLIST_NONE && g_playlistPlayer.IsShuffled(iPlaylist))
1360      g_playlistPlayer.SetShuffle(iPlaylist, false);
1361
1362   // Call the base method to actually queue the items
1363   // and start playing the given item
1364   return CGUIMediaWindow::OnPlayAndQueueMedia(item);
1365 }
1366
1367 void CGUIWindowVideoBase::PlayMovie(const CFileItem *item)
1368 {
1369   CFileItemList movieList;
1370   int selectedFile = 1;
1371   long startoffset = item->m_lStartOffset;
1372
1373   if (item->IsStack() && (!g_guiSettings.GetBool("myvideos.treatstackasfile") ||
1374                           CFileItem(CStackDirectory::GetFirstStackedFile(item->m_strPath),false).IsDVDImage()) )
1375   {
1376     CStdStringArray movies;
1377     GetStackedFiles(item->m_strPath, movies);
1378
1379     if (item->m_lStartOffset == STARTOFFSET_RESUME)
1380     {
1381       startoffset = GetResumeItemOffset(item);
1382
1383       if (startoffset & 0xF0000000) /* file is specified as a flag */
1384       {
1385         selectedFile = (startoffset>>28);
1386         startoffset = startoffset & ~0xF0000000;
1387       }
1388       else
1389       {
1390         /* attempt to start on a specific time in a stack */
1391         /* if we are lucky, we might have stored timings for */
1392         /* this stack at some point */
1393
1394         m_database.Open();
1395
1396         /* figure out what file this time offset is */
1397         vector<int> times;
1398         m_database.GetStackTimes(item->m_strPath, times);
1399         long totaltime = 0;
1400         for (unsigned i = 0; i < times.size(); i++)
1401         {
1402           totaltime += times[i]*75;
1403           if (startoffset < totaltime )
1404           {
1405             selectedFile = i+1;
1406             startoffset -= totaltime - times[i]*75; /* rebase agains selected file */
1407             break;
1408           }
1409         }
1410         m_database.Close();
1411       }
1412     }
1413     else
1414     { // show file stacking dialog
1415       CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)g_windowManager.GetWindow(WINDOW_DIALOG_FILESTACKING);
1416       if (dlg)
1417       {
1418         dlg->SetNumberOfFiles(movies.size());
1419         dlg->DoModal();
1420         selectedFile = dlg->GetSelectedFile();
1421         if (selectedFile < 1)
1422           return;
1423       }
1424     }
1425     // add to our movie list
1426     for (unsigned int i = 0; i < movies.size(); i++)
1427     {
1428       CFileItemPtr movieItem(new CFileItem(movies[i], false));
1429       movieList.Add(movieItem);
1430     }
1431   }
1432   else
1433   {
1434     CFileItemPtr movieItem(new CFileItem(*item));
1435     movieList.Add(movieItem);
1436   }
1437
1438   g_playlistPlayer.Reset();
1439   g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
1440   CPlayList& playlist = g_playlistPlayer.GetPlaylist(PLAYLIST_VIDEO);
1441   playlist.Clear();
1442   for (int i = selectedFile - 1; i < (int)movieList.Size(); ++i)
1443   {
1444     if (i == selectedFile - 1)
1445       movieList[i]->m_lStartOffset = startoffset;
1446     playlist.Add(movieList[i]);
1447   }
1448
1449   if(m_thumbLoader.IsLoading())
1450     m_thumbLoader.StopAsync();
1451
1452   // play movie...
1453   g_playlistPlayer.Play(0);
1454
1455   if(!g_application.IsPlayingVideo())
1456     m_thumbLoader.Load(*m_vecItems);
1457 }
1458
1459 void CGUIWindowVideoBase::OnDeleteItem(int iItem)
1460 {
1461   if ( iItem < 0 || iItem >= m_vecItems->Size())
1462     return;
1463
1464   OnDeleteItem(m_vecItems->Get(iItem));
1465
1466   Update(m_vecItems->m_strPath);
1467   m_viewControl.SetSelectedItem(iItem);
1468 }
1469
1470 void CGUIWindowVideoBase::OnDeleteItem(CFileItemPtr item)
1471 {
1472   // HACK: stacked files need to be treated as folders in order to be deleted
1473   if (item->IsStack())
1474     item->m_bIsFolder = true;
1475   if (g_settings.GetCurrentProfile().getLockMode() != LOCK_MODE_EVERYONE &&
1476       g_settings.GetCurrentProfile().filesLocked())
1477   {
1478     if (!g_passwordManager.IsMasterLockUnlocked(true))
1479       return;
1480   }
1481
1482   if (g_guiSettings.GetBool("filelists.allowfiledeletion") &&
1483       CUtil::SupportsFileOperations(item->m_strPath))
1484     CFileUtils::DeleteItem(item);
1485 }
1486
1487 void CGUIWindowVideoBase::MarkWatched(const CFileItemPtr &item, bool bMark)
1488 {
1489   if (!g_settings.GetCurrentProfile().canWriteDatabases())
1490     return;
1491   // dont allow update while scanning
1492   CGUIDialogVideoScan* pDialogScan = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1493   if (pDialogScan && pDialogScan->IsScanning())
1494   {
1495     CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0);
1496     return;
1497   }
1498
1499   CVideoDatabase database;
1500   if (database.Open())
1501   {
1502     CFileItemList items;
1503     if (item->m_bIsFolder)
1504     {
1505       CStdString strPath = item->m_strPath;
1506       CDirectory::GetDirectory(strPath, items);
1507     }
1508     else
1509       items.Add(item);
1510
1511     for (int i=0;i<items.Size();++i)
1512     {
1513       CFileItemPtr pItem=items[i];
1514
1515       if (pItem->HasVideoInfoTag() &&
1516           (( bMark && pItem->GetVideoInfoTag()->m_playCount) ||
1517            (!bMark && !(pItem->GetVideoInfoTag()->m_playCount))))
1518         continue;
1519
1520       // Clear resume bookmark
1521       if (bMark)
1522         database.ClearBookMarksOfFile(pItem->m_strPath, CBookmark::RESUME);
1523
1524       database.SetPlayCount(*pItem, bMark ? 1 : 0);
1525     }
1526     
1527     database.Close(); 
1528   }
1529 }
1530
1531 //Add change a title's name
1532 void CGUIWindowVideoBase::UpdateVideoTitle(const CFileItem* pItem)
1533 {
1534   // dont allow update while scanning
1535   CGUIDialogVideoScan* pDialogScan = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1536   if (pDialogScan && pDialogScan->IsScanning())
1537   {
1538     CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0);
1539     return;
1540   }
1541
1542   CVideoInfoTag detail;
1543   CVideoDatabase database;
1544   database.Open();
1545   CVideoDatabaseDirectory dir;
1546   CQueryParams params;
1547   dir.GetQueryParams(pItem->m_strPath,params);
1548   int iDbId = pItem->GetVideoInfoTag()->m_iDbId;
1549
1550   VIDEODB_CONTENT_TYPE iType=VIDEODB_CONTENT_MOVIES;
1551   if (pItem->HasVideoInfoTag() && (!pItem->GetVideoInfoTag()->m_strShowTitle.IsEmpty() ||
1552       pItem->GetVideoInfoTag()->m_iEpisode > 0))
1553   {
1554     iType = VIDEODB_CONTENT_TVSHOWS;
1555   }
1556   if (pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iSeason > -1 && !pItem->m_bIsFolder)
1557     iType = VIDEODB_CONTENT_EPISODES;
1558   if (pItem->HasVideoInfoTag() && !pItem->GetVideoInfoTag()->m_strArtist.IsEmpty())
1559     iType = VIDEODB_CONTENT_MUSICVIDEOS;
1560   if (params.GetSetId() != -1 && params.GetMovieId() == -1)
1561     iType = VIDEODB_CONTENT_MOVIE_SETS;
1562   if (iType == VIDEODB_CONTENT_MOVIES)
1563     database.GetMovieInfo("", detail, pItem->GetVideoInfoTag()->m_iDbId);
1564   if (iType == VIDEODB_CONTENT_MOVIE_SETS)
1565   {
1566     database.GetSetById(params.GetSetId(),detail.m_strTitle);
1567     iDbId = params.GetSetId();
1568   }
1569   if (iType == VIDEODB_CONTENT_EPISODES)
1570     database.GetEpisodeInfo(pItem->m_strPath,detail,pItem->GetVideoInfoTag()->m_iDbId);
1571   if (iType == VIDEODB_CONTENT_TVSHOWS)
1572     database.GetTvShowInfo(pItem->GetVideoInfoTag()->m_strFileNameAndPath,detail,pItem->GetVideoInfoTag()->m_iDbId);
1573   if (iType == VIDEODB_CONTENT_MUSICVIDEOS)
1574     database.GetMusicVideoInfo(pItem->GetVideoInfoTag()->m_strFileNameAndPath,detail,pItem->GetVideoInfoTag()->m_iDbId);
1575
1576   CStdString strInput;
1577   strInput = detail.m_strTitle;
1578
1579   //Get the new title
1580   if (!CGUIDialogKeyboard::ShowAndGetInput(strInput, g_localizeStrings.Get(16105), false))
1581     return;
1582
1583   database.UpdateMovieTitle(iDbId, strInput, iType);
1584 }
1585
1586 void CGUIWindowVideoBase::LoadPlayList(const CStdString& strPlayList, int iPlayList /* = PLAYLIST_VIDEO */)
1587 {
1588   // if partymode is active, we disable it
1589   if (g_partyModeManager.IsEnabled())
1590     g_partyModeManager.Disable();
1591
1592   // load a playlist like .m3u, .pls
1593   // first get correct factory to load playlist
1594   auto_ptr<CPlayList> pPlayList (CPlayListFactory::Create(strPlayList));
1595   if (pPlayList.get())
1596   {
1597     // load it
1598     if (!pPlayList->Load(strPlayList))
1599     {
1600       CGUIDialogOK::ShowAndGetInput(6, 0, 477, 0);
1601       return; //hmmm unable to load playlist?
1602     }
1603   }
1604
1605   if (g_application.ProcessAndStartPlaylist(strPlayList, *pPlayList, iPlayList))
1606   {
1607     if (m_guiState.get())
1608       m_guiState->SetPlaylistDirectory("playlistvideo://");
1609   }
1610 }
1611
1612 void CGUIWindowVideoBase::PlayItem(int iItem)
1613 {
1614   // restrictions should be placed in the appropiate window code
1615   // only call the base code if the item passes since this clears
1616   // the currently playing temp playlist
1617
1618   const CFileItemPtr pItem = m_vecItems->Get(iItem);
1619   // if its a folder, build a temp playlist
1620   if (pItem->m_bIsFolder && !pItem->IsPlugin())
1621   {
1622     // take a copy so we can alter the queue state
1623     CFileItemPtr item(new CFileItem(*m_vecItems->Get(iItem)));
1624
1625     //  Allow queuing of unqueueable items
1626     //  when we try to queue them directly
1627     if (!item->CanQueue())
1628       item->SetCanQueue(true);
1629
1630     // skip ".."
1631     if (item->IsParentFolder())
1632       return;
1633
1634     // recursively add items to list
1635     CFileItemList queuedItems;
1636     AddItemToPlayList(item, queuedItems);
1637
1638     g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO);
1639     g_playlistPlayer.Reset();
1640     g_playlistPlayer.Add(PLAYLIST_VIDEO, queuedItems);
1641     g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO);
1642     g_playlistPlayer.Play();
1643   }
1644   else if (pItem->IsPlayList())
1645   {
1646     // load the playlist the old way
1647     LoadPlayList(pItem->m_strPath, PLAYLIST_VIDEO);
1648   }
1649   else
1650   {
1651     // single item, play it
1652     OnClick(iItem);
1653   }
1654 }
1655
1656 bool CGUIWindowVideoBase::Update(const CStdString &strDirectory)
1657 {
1658   if (m_thumbLoader.IsLoading())
1659     m_thumbLoader.StopThread();
1660
1661   if (!CGUIMediaWindow::Update(strDirectory))
1662     return false;
1663
1664   m_thumbLoader.Load(*m_vecItems);
1665
1666   return true;
1667 }
1668
1669 bool CGUIWindowVideoBase::GetDirectory(const CStdString &strDirectory, CFileItemList &items)
1670 {
1671   bool bResult = CGUIMediaWindow::GetDirectory(strDirectory,items);
1672
1673   // add in the "New Playlist" item if we're in the playlists folder
1674   if ((items.m_strPath == "special://videoplaylists/") && !items.Contains("newplaylist://"))
1675   {
1676     CFileItemPtr newPlaylist(new CFileItem(g_settings.GetUserDataItem("PartyMode-Video.xsp"),false));
1677     newPlaylist->SetLabel(g_localizeStrings.Get(16035));
1678     newPlaylist->SetLabelPreformated(true);
1679     newPlaylist->m_bIsFolder = true;
1680     items.Add(newPlaylist);
1681
1682 /*    newPlaylist.reset(new CFileItem("newplaylist://", false));
1683     newPlaylist->SetLabel(g_localizeStrings.Get(525));
1684     newPlaylist->SetLabelPreformated(true);
1685     items.Add(newPlaylist);
1686 */
1687     newPlaylist.reset(new CFileItem("newsmartplaylist://video", false));
1688     newPlaylist->SetLabel(g_localizeStrings.Get(21437));  // "new smart playlist..."
1689     newPlaylist->SetLabelPreformated(true);
1690     items.Add(newPlaylist);
1691   }
1692
1693   m_stackingAvailable = !(items.IsTuxBox() || items.IsPlugin() ||
1694                           items.IsAddonsPath() || items.IsRSS() ||
1695                           items.IsInternetStream() || items.IsVideoDb());
1696   // we may also be in a tvshow files listing
1697   // (ideally this should be removed, and our stack regexps tidied up if necessary
1698   // No "normal" episodes should stack, and multi-parts should be supported)
1699   ADDON::ScraperPtr info = m_database.GetScraperForPath(strDirectory);
1700   if (info && info->Content() == CONTENT_TVSHOWS)
1701     m_stackingAvailable = false;
1702
1703   if (m_stackingAvailable && !items.IsStack() && g_settings.m_videoStacking)
1704     items.Stack();
1705
1706   return bResult;
1707 }
1708
1709 void CGUIWindowVideoBase::OnPrepareFileItems(CFileItemList &items)
1710 {
1711   if (!items.m_strPath.Equals("plugin://video/"))
1712     items.SetCachedVideoThumbs();
1713
1714   if (items.GetContent() != "episodes")
1715   { // we don't set cached fanart for episodes, as this requires a db fetch per episode
1716     for (int i = 0; i < items.Size(); ++i)
1717     {
1718       CFileItemPtr item = items[i];
1719       if (!item->HasProperty("fanart_image"))
1720       {
1721         CStdString art = item->GetCachedFanart();
1722         if (CFile::Exists(art))
1723           item->SetProperty("fanart_image", art);
1724       }
1725     }
1726   }
1727 }
1728
1729 void CGUIWindowVideoBase::AddToDatabase(int iItem)
1730 {
1731   if (iItem < 0 || iItem >= m_vecItems->Size())
1732     return;
1733
1734   CFileItemPtr pItem = m_vecItems->Get(iItem);
1735   if (pItem->IsParentFolder() || pItem->m_bIsFolder)
1736     return;
1737
1738   CVideoInfoTag movie;
1739   movie.Reset();
1740
1741   // prompt for data
1742   // enter a new title
1743   CStdString strTitle = pItem->GetLabel();
1744   if (!CGUIDialogKeyboard::ShowAndGetInput(strTitle, g_localizeStrings.Get(528), false)) // Enter Title
1745     return;
1746
1747   // pick genre
1748   CGUIDialogSelect* pSelect = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
1749   if (!pSelect)
1750     return;
1751
1752   pSelect->SetHeading(530); // Select Genre
1753   pSelect->Reset();
1754   CFileItemList items;
1755   if (!CDirectory::GetDirectory("videodb://1/1/", items))
1756     return;
1757   pSelect->SetItems(&items);
1758   pSelect->EnableButton(true, 531); // New Genre
1759   pSelect->DoModal();
1760   CStdString strGenre;
1761   int iSelected = pSelect->GetSelectedLabel();
1762   if (iSelected >= 0)
1763     strGenre = items[iSelected]->GetLabel();
1764   else if (!pSelect->IsButtonPressed())
1765     return;
1766
1767   // enter new genre string
1768   if (strGenre.IsEmpty())
1769   {
1770     strGenre = g_localizeStrings.Get(532); // Manual Addition
1771     if (!CGUIDialogKeyboard::ShowAndGetInput(strGenre, g_localizeStrings.Get(533), false)) // Enter Genre
1772       return; // user backed out
1773     if (strGenre.IsEmpty())
1774       return; // no genre string
1775   }
1776
1777   // set movie info
1778   movie.m_strTitle = strTitle;
1779   movie.m_strGenre = strGenre;
1780
1781   // everything is ok, so add to database
1782   m_database.Open();
1783   int idMovie = m_database.AddMovie(pItem->m_strPath);
1784   movie.m_strIMDBNumber.Format("xx%08i", idMovie);
1785   m_database.SetDetailsForMovie(pItem->m_strPath, movie);
1786   m_database.Close();
1787
1788   // done...
1789   CGUIDialogOK::ShowAndGetInput(20177, movie.m_strTitle, movie.m_strGenre, movie.m_strIMDBNumber);
1790
1791   // library view cache needs to be cleared
1792   CUtil::DeleteVideoDatabaseDirectoryCache();
1793 }
1794
1795 /// \brief Search the current directory for a string got from the virtual keyboard
1796 void CGUIWindowVideoBase::OnSearch()
1797 {
1798   CStdString strSearch;
1799   if (!CGUIDialogKeyboard::ShowAndGetInput(strSearch, g_localizeStrings.Get(16017), false))
1800     return ;
1801
1802   strSearch.ToLower();
1803   if (m_dlgProgress)
1804   {
1805     m_dlgProgress->SetHeading(194);
1806     m_dlgProgress->SetLine(0, strSearch);
1807     m_dlgProgress->SetLine(1, "");
1808     m_dlgProgress->SetLine(2, "");
1809     m_dlgProgress->StartModal();
1810     m_dlgProgress->Progress();
1811   }
1812   CFileItemList items;
1813   DoSearch(strSearch, items);
1814
1815   if (m_dlgProgress)
1816     m_dlgProgress->Close();
1817
1818   if (items.Size())
1819   {
1820     CGUIDialogSelect* pDlgSelect = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT);
1821     pDlgSelect->Reset();
1822     pDlgSelect->SetHeading(283);
1823
1824     for (int i = 0; i < (int)items.Size(); i++)
1825     {
1826       CFileItemPtr pItem = items[i];
1827       pDlgSelect->Add(pItem->GetLabel());
1828     }
1829
1830     pDlgSelect->DoModal();
1831
1832     int iItem = pDlgSelect->GetSelectedLabel();
1833     if (iItem < 0)
1834       return;
1835
1836     CFileItemPtr pSelItem = items[iItem];
1837
1838     OnSearchItemFound(pSelItem.get());
1839   }
1840   else
1841   {
1842     CGUIDialogOK::ShowAndGetInput(194, 284, 0, 0);
1843   }
1844 }
1845
1846 /// \brief React on the selected search item
1847 /// \param pItem Search result item
1848 void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem)
1849 {
1850   if (pSelItem->m_bIsFolder)
1851   {
1852     CStdString strPath = pSelItem->m_strPath;
1853     CStdString strParentPath;
1854     URIUtils::GetParentPath(strPath, strParentPath);
1855
1856     Update(strParentPath);
1857
1858     if (pSelItem->IsVideoDb() && g_settings.m_bMyVideoNavFlatten)
1859       SetHistoryForPath("");
1860     else
1861       SetHistoryForPath(strParentPath);
1862
1863     strPath = pSelItem->m_strPath;
1864     CURL url(strPath);
1865     if (pSelItem->IsSmb() && !URIUtils::HasSlashAtEnd(strPath))
1866       strPath += "/";
1867
1868     for (int i = 0; i < m_vecItems->Size(); i++)
1869     {
1870       CFileItemPtr pItem = m_vecItems->Get(i);
1871       if (pItem->m_strPath == strPath)
1872       {
1873         m_viewControl.SetSelectedItem(i);
1874         break;
1875       }
1876     }
1877   }
1878   else
1879   {
1880     CStdString strPath;
1881     URIUtils::GetDirectory(pSelItem->m_strPath, strPath);
1882
1883     Update(strPath);
1884
1885     if (pSelItem->IsVideoDb() && g_settings.m_bMyVideoNavFlatten)
1886       SetHistoryForPath("");
1887     else
1888       SetHistoryForPath(strPath);
1889
1890     for (int i = 0; i < (int)m_vecItems->Size(); i++)
1891     {
1892       CFileItemPtr pItem = m_vecItems->Get(i);
1893       if (pItem->m_strPath == pSelItem->m_strPath)
1894       {
1895         m_viewControl.SetSelectedItem(i);
1896         break;
1897       }
1898     }
1899   }
1900   m_viewControl.SetFocused();
1901 }
1902
1903 int CGUIWindowVideoBase::GetScraperForItem(CFileItem *item, ADDON::ScraperPtr &info, SScanSettings& settings)
1904 {
1905   if (!item)
1906     return 0;
1907
1908   if (m_vecItems->IsPlugin() || m_vecItems->IsRSS())
1909   {
1910     info.reset();
1911     return 0;
1912   }
1913   else if(m_vecItems->IsLiveTV())
1914   {
1915     info.reset();
1916     return 0;
1917   }
1918
1919   bool foundDirectly = false;
1920   info = m_database.GetScraperForPath(item->HasVideoInfoTag() ? item->GetVideoInfoTag()->m_strPath : item->m_strPath, settings, foundDirectly);
1921   return foundDirectly ? 1 : 0;
1922 }
1923
1924 void CGUIWindowVideoBase::OnScan(const CStdString& strPath, bool scanAll)
1925 {
1926   CGUIDialogVideoScan* pDialog = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
1927   if (pDialog)
1928     pDialog->StartScanning(strPath, scanAll);
1929 }
1930
1931 CStdString CGUIWindowVideoBase::GetStartFolder(const CStdString &dir)
1932 {
1933   if (dir.Equals("$PLAYLISTS") || dir.Equals("Playlists"))
1934     return "special://videoplaylists/";
1935   else if (dir.Equals("Plugins") || dir.Equals("Addons"))
1936     return "addons://sources/video/";
1937   return CGUIMediaWindow::GetStartFolder(dir);
1938 }
1939
1940 void CGUIWindowVideoBase::AppendAndClearSearchItems(CFileItemList &searchItems, const CStdString &prependLabel, CFileItemList &results)
1941 {
1942   if (!searchItems.Size())
1943     return;
1944
1945   searchItems.Sort(g_guiSettings.GetBool("filelists.ignorethewhensorting") ? SORT_METHOD_LABEL_IGNORE_THE : SORT_METHOD_LABEL, SORT_ORDER_ASC);
1946   for (int i = 0; i < searchItems.Size(); i++)
1947     searchItems[i]->SetLabel(prependLabel + searchItems[i]->GetLabel());
1948   results.Append(searchItems);
1949
1950   searchItems.Clear();
1951 }
1952
1953 bool CGUIWindowVideoBase::OnUnAssignContent(const CStdString &path, int label1, int label2, int label3)
1954 {
1955   bool bCanceled;
1956   CVideoDatabase db;
1957   db.Open();
1958   if (CGUIDialogYesNo::ShowAndGetInput(label1,label2,label3,20022,bCanceled))
1959   {
1960     db.RemoveContentForPath(path);
1961     db.Close();
1962     CUtil::DeleteVideoDatabaseDirectoryCache();
1963     return true;
1964   }
1965   else
1966   {
1967     if (!bCanceled)
1968     {
1969       ADDON::ScraperPtr info;
1970       SScanSettings settings;
1971       settings.exclude = true;
1972       db.SetScraperForPath(path,info,settings);
1973     }
1974   }
1975   db.Close();
1976   
1977   return false;
1978 }
1979
1980 void CGUIWindowVideoBase::OnAssignContent(const CStdString &path, int iFound, ADDON::ScraperPtr& info, SScanSettings& settings)
1981 {
1982   bool bScan=false;
1983   CVideoDatabase db;
1984   db.Open();
1985   if (iFound == 0)
1986   {
1987     info = db.GetScraperForPath(path, settings);
1988   }
1989   
1990   ADDON::ScraperPtr info2(info);
1991   
1992   if (CGUIDialogContentSettings::Show(info, settings, bScan))
1993   {
1994     if(settings.exclude || (!info && info2))
1995     {
1996       OnUnAssignContent(path,20375,20340,20341);
1997     }
1998     else if (info != info2)
1999     {
2000       if (OnUnAssignContent(path,20442,20443,20444))
2001         bScan = true;
2002     }
2003     
2004     db.SetScraperForPath(path,info,settings);
2005     
2006     if (bScan)
2007     {
2008       CGUIDialogVideoScan* pDialog = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
2009       if (pDialog)
2010         pDialog->StartScanning(path, true);
2011     }
2012   }
2013 }