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