[windows] Fix MAC Address Discovery
[xbmc.git] / xbmc / filesystem / BlurayDirectory.cpp
blob322b662fd9ae3b578980d0373b079a094a4a27fd
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8 #include "BlurayDirectory.h"
10 #include "File.h"
11 #include "FileItem.h"
12 #include "FileItemList.h"
13 #include "LangInfo.h"
14 #include "URL.h"
15 #include "filesystem/BlurayCallback.h"
16 #include "filesystem/Directory.h"
17 #include "guilib/LocalizeStrings.h"
18 #include "utils/LangCodeExpander.h"
19 #include "utils/RegExp.h"
20 #include "utils/StringUtils.h"
21 #include "utils/URIUtils.h"
22 #include "utils/log.h"
23 #include "video/VideoInfoTag.h"
25 #include <array>
26 #include <cassert>
27 #include <climits>
28 #include <memory>
29 #include <stdlib.h>
30 #include <string>
32 #include <libbluray/bluray-version.h>
33 #include <libbluray/bluray.h>
34 #include <libbluray/filesystem.h>
35 #include <libbluray/log_control.h>
37 namespace XFILE
40 #define MAIN_TITLE_LENGTH_PERCENT 70 /** Minimum length of main titles, based on longest title */
42 CBlurayDirectory::~CBlurayDirectory()
44 Dispose();
47 void CBlurayDirectory::Dispose()
49 if(m_bd)
51 bd_close(m_bd);
52 m_bd = nullptr;
56 std::string CBlurayDirectory::GetBlurayTitle()
58 return GetDiscInfoString(DiscInfo::TITLE);
61 std::string CBlurayDirectory::GetBlurayID()
63 return GetDiscInfoString(DiscInfo::ID);
66 std::string CBlurayDirectory::GetDiscInfoString(DiscInfo info)
68 switch (info)
70 case XFILE::CBlurayDirectory::DiscInfo::TITLE:
72 if (!m_blurayInitialized)
73 return "";
74 const BLURAY_DISC_INFO* disc_info = bd_get_disc_info(m_bd);
75 if (!disc_info || !disc_info->bluray_detected)
76 return "";
78 std::string title = "";
80 #if (BLURAY_VERSION > BLURAY_VERSION_CODE(1,0,0))
81 title = disc_info->disc_name ? disc_info->disc_name : "";
82 #endif
84 return title;
86 case XFILE::CBlurayDirectory::DiscInfo::ID:
88 if (!m_blurayInitialized)
89 return "";
91 const BLURAY_DISC_INFO* disc_info = bd_get_disc_info(m_bd);
92 if (!disc_info || !disc_info->bluray_detected)
93 return "";
95 std::string id = "";
97 #if (BLURAY_VERSION > BLURAY_VERSION_CODE(1,0,0))
98 id = disc_info->udf_volume_id ? disc_info->udf_volume_id : "";
100 if (id.empty())
102 id = HexToString(disc_info->disc_id, 20);
104 #endif
106 return id;
108 default:
109 break;
112 return "";
115 std::shared_ptr<CFileItem> CBlurayDirectory::GetTitle(const BLURAY_TITLE_INFO* title,
116 const std::string& label)
118 std::string buf;
119 std::string chap;
120 CFileItemPtr item(new CFileItem("", false));
121 CURL path(m_url);
122 buf = StringUtils::Format("BDMV/PLAYLIST/{:05}.mpls", title->playlist);
123 path.SetFileName(buf);
124 item->SetPath(path.Get());
125 int duration = (int)(title->duration / 90000);
126 item->GetVideoInfoTag()->SetDuration(duration);
127 item->GetVideoInfoTag()->m_iTrack = title->playlist;
128 buf = StringUtils::Format(label, title->playlist);
129 item->m_strTitle = buf;
130 item->SetLabel(buf);
131 chap = StringUtils::Format(g_localizeStrings.Get(25007), title->chapter_count,
132 StringUtils::SecondsToTimeString(duration));
133 item->SetLabel2(chap);
134 item->m_dwSize = 0;
135 item->SetArt("icon", "DefaultVideo.png");
136 for(unsigned int i = 0; i < title->clip_count; ++i)
137 item->m_dwSize += title->clips[i].pkt_count * 192;
139 return item;
142 void CBlurayDirectory::GetTitles(bool main, CFileItemList &items)
144 std::vector<BLURAY_TITLE_INFO*> titleList;
145 uint64_t minDuration = 0;
147 // Searching for a user provided list of playlists.
148 if (main)
149 titleList = GetUserPlaylists();
151 if (!main || titleList.empty())
153 uint32_t numTitles = bd_get_titles(m_bd, TITLES_RELEVANT, 0);
155 for (uint32_t i = 0; i < numTitles; i++)
157 BLURAY_TITLE_INFO* t = bd_get_title_info(m_bd, i, 0);
159 if (!t)
161 CLog::Log(LOGDEBUG, "CBlurayDirectory - unable to get title {}", i);
162 continue;
165 if (main && t->duration > minDuration)
166 minDuration = t->duration;
168 titleList.emplace_back(t);
172 minDuration = minDuration * MAIN_TITLE_LENGTH_PERCENT / 100;
174 for (auto& title : titleList)
176 if (title->duration < minDuration)
177 continue;
179 items.Add(GetTitle(title, main ? g_localizeStrings.Get(25004) /* Main Title */ : g_localizeStrings.Get(25005) /* Title */));
180 bd_free_title_info(title);
184 void CBlurayDirectory::GetRoot(CFileItemList &items)
186 GetTitles(true, items);
188 CURL path(m_url);
189 CFileItemPtr item;
191 path.SetFileName(URIUtils::AddFileToFolder(m_url.GetFileName(), "titles"));
192 item = std::make_shared<CFileItem>();
193 item->SetPath(path.Get());
194 item->m_bIsFolder = true;
195 item->SetLabel(g_localizeStrings.Get(25002) /* All titles */);
196 item->SetArt("icon", "DefaultVideoPlaylists.png");
197 items.Add(item);
199 const BLURAY_DISC_INFO* disc_info = bd_get_disc_info(m_bd);
200 if (disc_info && disc_info->no_menu_support)
202 CLog::Log(LOGDEBUG, "CBlurayDirectory::GetRoot - no menu support, skipping menu entry");
203 return;
206 path.SetFileName("menu");
207 item = std::make_shared<CFileItem>();
208 item->SetPath(path.Get());
209 item->m_bIsFolder = false;
210 item->SetLabel(g_localizeStrings.Get(25003) /* Menus */);
211 item->SetArt("icon", "DefaultProgram.png");
212 items.Add(item);
215 bool CBlurayDirectory::GetDirectory(const CURL& url, CFileItemList &items)
217 Dispose();
218 m_url = url;
219 std::string root = m_url.GetHostName();
220 std::string file = m_url.GetFileName();
221 URIUtils::RemoveSlashAtEnd(file);
222 URIUtils::RemoveSlashAtEnd(root);
224 if (!InitializeBluray(root))
225 return false;
227 if(file == "root")
228 GetRoot(items);
229 else if(file == "root/titles")
230 GetTitles(false, items);
231 else
233 CURL url2 = GetUnderlyingCURL(url);
234 CDirectory::CHints hints;
235 hints.flags = m_flags;
236 if (!CDirectory::GetDirectory(url2, items, hints))
237 return false;
240 items.AddSortMethod(SortByTrackNumber, 554, LABEL_MASKS("%L", "%D", "%L", "")); // FileName, Duration | Foldername, empty
241 items.AddSortMethod(SortBySize, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // FileName, Size | Foldername, Size
243 return true;
246 CURL CBlurayDirectory::GetUnderlyingCURL(const CURL& url)
248 assert(url.IsProtocol("bluray"));
249 std::string host = url.GetHostName();
250 const std::string& filename = url.GetFileName();
251 return CURL(host.append(filename));
254 bool CBlurayDirectory::InitializeBluray(const std::string &root)
256 bd_set_debug_handler(CBlurayCallback::bluray_logger);
257 bd_set_debug_mask(DBG_CRIT | DBG_BLURAY | DBG_NAV);
259 m_bd = bd_init();
261 if (!m_bd)
263 CLog::Log(LOGERROR, "CBlurayDirectory::InitializeBluray - failed to initialize libbluray");
264 return false;
267 std::string langCode;
268 g_LangCodeExpander.ConvertToISO6392T(g_langInfo.GetDVDMenuLanguage(), langCode);
269 bd_set_player_setting_str(m_bd, BLURAY_PLAYER_SETTING_MENU_LANG, langCode.c_str());
271 if (!bd_open_files(m_bd, const_cast<std::string*>(&root), CBlurayCallback::dir_open, CBlurayCallback::file_open))
273 CLog::Log(LOGERROR, "CBlurayDirectory::InitializeBluray - failed to open {}",
274 CURL::GetRedacted(root));
275 return false;
277 m_blurayInitialized = true;
279 return true;
282 std::string CBlurayDirectory::HexToString(const uint8_t *buf, int count)
284 std::array<char, 42> tmp;
286 for (int i = 0; i < count; i++)
288 sprintf(tmp.data() + (i * 2), "%02x", buf[i]);
291 return std::string(std::begin(tmp), std::end(tmp));
294 std::vector<BLURAY_TITLE_INFO*> CBlurayDirectory::GetUserPlaylists()
296 std::string root = m_url.GetHostName();
297 std::string discInfPath = URIUtils::AddFileToFolder(root, "disc.inf");
298 std::vector<BLURAY_TITLE_INFO*> userTitles;
299 CFile file;
300 char buffer[1025];
302 if (file.Open(discInfPath))
304 CLog::Log(LOGDEBUG, "CBlurayDirectory::GetTitles - disc.inf found");
306 CRegExp pl(true);
307 if (!pl.RegComp("(\\d+)"))
309 file.Close();
310 return userTitles;
313 uint8_t maxLines = 100;
314 while ((maxLines > 0) && file.ReadString(buffer, 1024))
316 maxLines--;
317 if (StringUtils::StartsWithNoCase(buffer, "playlists"))
319 int pos = 0;
320 while ((pos = pl.RegFind(buffer, static_cast<unsigned int>(pos))) >= 0)
322 std::string playlist = pl.GetMatch(0);
323 uint32_t len = static_cast<uint32_t>(playlist.length());
325 if (len <= 5)
327 unsigned long int plNum = strtoul(playlist.c_str(), nullptr, 10);
329 BLURAY_TITLE_INFO* t = bd_get_playlist_info(m_bd, static_cast<uint32_t>(plNum), 0);
330 if (t)
331 userTitles.emplace_back(t);
334 if (static_cast<int64_t>(pos) + static_cast<int64_t>(len) > INT_MAX)
335 break;
336 else
337 pos += len;
341 file.Close();
343 return userTitles;
346 } /* namespace XFILE */