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