1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 
10 #include "GUIDialogSimpleMenu.h"
11 
12 #include "GUIDialogSelect.h"
13 #include "ServiceBroker.h"
14 #include "URL.h"
15 #include "dialogs/GUIDialogBusy.h"
16 #include "filesystem/Directory.h"
17 #include "filesystem/File.h"
18 #include "guilib/GUIComponent.h"
19 #include "guilib/GUIWindowManager.h"
20 #include "settings/DiscSettings.h"
21 #include "settings/Settings.h"
22 #include "settings/SettingsComponent.h"
23 #include "threads/IRunnable.h"
24 #include "utils/URIUtils.h"
25 #include "utils/Variant.h"
26 #include "utils/log.h"
27 #include "video/VideoInfoTag.h"
28 
29 namespace
30 {
31 class CGetDirectoryItems : public IRunnable
32 {
33 public:
CGetDirectoryItems(const std::string & path,CFileItemList & items,const XFILE::CDirectory::CHints & hints)34   CGetDirectoryItems(const std::string &path, CFileItemList &items, const XFILE::CDirectory::CHints &hints)
35   : m_path(path), m_items(items), m_hints(hints)
36   {
37   }
Run()38   void Run() override
39   {
40     m_result = XFILE::CDirectory::GetDirectory(m_path, m_items, m_hints);
41   }
42   bool m_result;
43 protected:
44   std::string m_path;
45   CFileItemList &m_items;
46   XFILE::CDirectory::CHints m_hints;
47 };
48 }
49 
50 
ShowPlaySelection(CFileItem & item)51 bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item)
52 {
53   if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_DISC_PLAYBACK) != BD_PLAYBACK_SIMPLE_MENU)
54     return true;
55 
56   std::string path;
57   if (item.IsVideoDb())
58     path = item.GetVideoInfoTag()->m_strFileNameAndPath;
59   else
60     path = item.GetPath();
61 
62   if (item.IsBDFile())
63   {
64     std::string root = URIUtils::GetParentPath(item.GetDynPath());
65     URIUtils::RemoveSlashAtEnd(root);
66     if (URIUtils::GetFileName(root) == "BDMV")
67     {
68       CURL url("bluray://");
69       url.SetHostName(URIUtils::GetParentPath(root));
70       url.SetFileName("root");
71       return ShowPlaySelection(item, url.Get());
72     }
73   }
74 
75   if (item.IsDiscImage())
76   {
77     CURL url2("udf://");
78     url2.SetHostName(item.GetDynPath());
79     url2.SetFileName("BDMV/index.bdmv");
80     if (XFILE::CFile::Exists(url2.Get()))
81     {
82       url2.SetFileName("");
83 
84       CURL url("bluray://");
85       url.SetHostName(url2.Get());
86       url.SetFileName("root");
87       return ShowPlaySelection(item, url.Get());
88     }
89   }
90   return true;
91 }
92 
ShowPlaySelection(CFileItem & item,const std::string & directory)93 bool CGUIDialogSimpleMenu::ShowPlaySelection(CFileItem& item, const std::string& directory)
94 {
95 
96   CFileItemList items;
97 
98   if (!GetDirectoryItems(directory, items, XFILE::CDirectory::CHints()))
99   {
100     CLog::Log(LOGERROR, "CGUIWindowVideoBase::ShowPlaySelection - Failed to get play directory for %s", directory.c_str());
101     return true;
102   }
103 
104   if (items.IsEmpty())
105   {
106     CLog::Log(LOGERROR, "CGUIWindowVideoBase::ShowPlaySelection - Failed to get any items %s", directory.c_str());
107     return true;
108   }
109 
110   CGUIDialogSelect* dialog = CServiceBroker::GetGUI()->GetWindowManager().GetWindow<CGUIDialogSelect>(WINDOW_DIALOG_SELECT);
111   while (true)
112   {
113     dialog->Reset();
114     dialog->SetHeading(CVariant{25006}); // Select playback item
115     dialog->SetItems(items);
116     dialog->SetUseDetails(true);
117     dialog->Open();
118 
119     CFileItemPtr item_new = dialog->GetSelectedFileItem();
120     if (!item_new || dialog->GetSelectedItem() < 0)
121     {
122       CLog::Log(LOGDEBUG, "CGUIWindowVideoBase::ShowPlaySelection - User aborted %s", directory.c_str());
123       break;
124     }
125 
126     if (item_new->m_bIsFolder == false)
127     {
128       std::string original_path = item.GetDynPath();
129       item.Reset();
130       item = *item_new;
131       item.SetProperty("original_listitem_url", original_path);
132       return true;
133     }
134 
135     items.Clear();
136     if (!GetDirectoryItems(item_new->GetDynPath(), items, XFILE::CDirectory::CHints()) || items.IsEmpty())
137     {
138       CLog::Log(LOGERROR, "CGUIWindowVideoBase::ShowPlaySelection - Failed to get any items %s", item_new->GetPath().c_str());
139       break;
140     }
141   }
142 
143   return false;
144 }
145 
GetDirectoryItems(const std::string & path,CFileItemList & items,const XFILE::CDirectory::CHints & hints)146 bool CGUIDialogSimpleMenu::GetDirectoryItems(const std::string &path, CFileItemList &items,
147                                              const XFILE::CDirectory::CHints &hints)
148 {
149   CGetDirectoryItems getItems(path, items, hints);
150   if (!CGUIDialogBusy::Wait(&getItems, 100, true))
151   {
152     return false;
153   }
154   return getItems.m_result;
155 }
156