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 #include "FileBrowser.h"
10
11 #include "URL.h"
12 #include "addons/binary-addons/AddonDll.h"
13 #include "addons/kodi-dev-kit/include/kodi/gui/dialogs/FileBrowser.h"
14 #include "dialogs/GUIDialogFileBrowser.h"
15 #include "settings/MediaSourceSettings.h"
16 #include "storage/MediaManager.h"
17 #include "utils/URIUtils.h"
18 #include "utils/log.h"
19
20 namespace ADDON
21 {
22
Init(AddonGlobalInterface * addonInterface)23 void Interface_GUIDialogFileBrowser::Init(AddonGlobalInterface* addonInterface)
24 {
25 addonInterface->toKodi->kodi_gui->dialogFileBrowser =
26 new AddonToKodiFuncTable_kodi_gui_dialogFileBrowser();
27
28 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_directory =
29 show_and_get_directory;
30 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file = show_and_get_file;
31 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file_from_dir =
32 show_and_get_file_from_dir;
33 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_file_list =
34 show_and_get_file_list;
35 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_source = show_and_get_source;
36 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_image = show_and_get_image;
37 addonInterface->toKodi->kodi_gui->dialogFileBrowser->show_and_get_image_list =
38 show_and_get_image_list;
39 addonInterface->toKodi->kodi_gui->dialogFileBrowser->clear_file_list = clear_file_list;
40 }
41
DeInit(AddonGlobalInterface * addonInterface)42 void Interface_GUIDialogFileBrowser::DeInit(AddonGlobalInterface* addonInterface)
43 {
44 delete addonInterface->toKodi->kodi_gui->dialogFileBrowser;
45 }
46
show_and_get_directory(KODI_HANDLE kodiBase,const char * shares,const char * heading,const char * path_in,char ** path_out,bool write_only)47 bool Interface_GUIDialogFileBrowser::show_and_get_directory(KODI_HANDLE kodiBase,
48 const char* shares,
49 const char* heading,
50 const char* path_in,
51 char** path_out,
52 bool write_only)
53 {
54 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
55 if (!addon)
56 {
57 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
58 return false;
59 }
60
61 if (!shares || !heading || !path_in || !path_out)
62 {
63 CLog::Log(LOGERROR,
64 "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
65 "heading='{}', path_in='{}', path_out='{}') on addon '{}'",
66 __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
67 static_cast<const void*>(path_in), static_cast<void*>(path_out), addon->ID());
68 return false;
69 }
70
71 std::string strPath = path_in;
72
73 VECSOURCES vecShares;
74 GetVECShares(vecShares, shares, strPath);
75 bool bRet = CGUIDialogFileBrowser::ShowAndGetDirectory(vecShares, heading, strPath, write_only);
76 if (bRet)
77 *path_out = strdup(strPath.c_str());
78 return bRet;
79 }
80
show_and_get_file(KODI_HANDLE kodiBase,const char * shares,const char * mask,const char * heading,const char * path_in,char ** path_out,bool use_thumbs,bool use_file_directories)81 bool Interface_GUIDialogFileBrowser::show_and_get_file(KODI_HANDLE kodiBase,
82 const char* shares,
83 const char* mask,
84 const char* heading,
85 const char* path_in,
86 char** path_out,
87 bool use_thumbs,
88 bool use_file_directories)
89 {
90 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
91 if (!addon)
92 {
93 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
94 return false;
95 }
96
97 if (!shares || !mask || !heading || !path_in || !path_out)
98 {
99 CLog::Log(LOGERROR,
100 "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', mask='{}', "
101 "heading='{}', path_in='{}', path_out='{}') on addon '{}'",
102 __func__, static_cast<const void*>(shares), static_cast<const void*>(mask),
103 static_cast<const void*>(heading), static_cast<const void*>(path_in),
104 static_cast<void*>(path_out), addon->ID());
105 return false;
106 }
107
108 std::string strPath = path_in;
109
110 VECSOURCES vecShares;
111 GetVECShares(vecShares, shares, strPath);
112 bool bRet = CGUIDialogFileBrowser::ShowAndGetFile(vecShares, mask, heading, strPath, use_thumbs,
113 use_file_directories);
114 if (bRet)
115 *path_out = strdup(strPath.c_str());
116 return bRet;
117 }
118
show_and_get_file_from_dir(KODI_HANDLE kodiBase,const char * directory,const char * mask,const char * heading,const char * path_in,char ** path_out,bool use_thumbs,bool use_file_directories,bool single_list)119 bool Interface_GUIDialogFileBrowser::show_and_get_file_from_dir(KODI_HANDLE kodiBase,
120 const char* directory,
121 const char* mask,
122 const char* heading,
123 const char* path_in,
124 char** path_out,
125 bool use_thumbs,
126 bool use_file_directories,
127 bool single_list)
128 {
129 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
130 if (!addon)
131 {
132 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
133 return false;
134 }
135
136 if (!directory || !mask || !heading || !path_in || !path_out)
137 {
138 CLog::Log(LOGERROR,
139 "Interface_GUIDialogFileBrowser::{} - invalid handler data (directory='{}', "
140 "mask='{}', heading='{}', path_in='{}', path_out='{}') on addon '{}'",
141 __func__, static_cast<const void*>(directory), static_cast<const void*>(mask),
142 static_cast<const void*>(heading), static_cast<const void*>(path_in),
143 static_cast<void*>(path_out), addon->ID());
144 return false;
145 }
146
147 std::string strPath = path_in;
148 bool bRet = CGUIDialogFileBrowser::ShowAndGetFile(directory, mask, heading, strPath, use_thumbs,
149 use_file_directories, single_list);
150 if (bRet)
151 *path_out = strdup(strPath.c_str());
152 return bRet;
153 }
154
show_and_get_file_list(KODI_HANDLE kodiBase,const char * shares,const char * mask,const char * heading,char *** file_list,unsigned int * entries,bool use_thumbs,bool use_file_directories)155 bool Interface_GUIDialogFileBrowser::show_and_get_file_list(KODI_HANDLE kodiBase,
156 const char* shares,
157 const char* mask,
158 const char* heading,
159 char*** file_list,
160 unsigned int* entries,
161 bool use_thumbs,
162 bool use_file_directories)
163 {
164 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
165 if (!addon)
166 {
167 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
168 return false;
169 }
170
171 if (!shares || !mask || !heading || !file_list || !entries)
172 {
173 CLog::Log(LOGERROR,
174 "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', mask='{}', "
175 "heading='{}', file_list='{}', entries='{}') on addon '{}'",
176 __func__, static_cast<const void*>(shares), static_cast<const void*>(mask),
177 static_cast<const void*>(heading), static_cast<void*>(file_list),
178 static_cast<void*>(entries), addon->ID());
179 return false;
180 }
181
182 VECSOURCES vecShares;
183 GetVECShares(vecShares, shares, "");
184
185 std::vector<std::string> pathsInt;
186 bool bRet = CGUIDialogFileBrowser::ShowAndGetFileList(vecShares, mask, heading, pathsInt,
187 use_thumbs, use_file_directories);
188 if (bRet)
189 {
190 *entries = pathsInt.size();
191 *file_list = static_cast<char**>(malloc(*entries * sizeof(char*)));
192 for (unsigned int i = 0; i < *entries; ++i)
193 (*file_list)[i] = strdup(pathsInt[i].c_str());
194 }
195 else
196 *entries = 0;
197 return bRet;
198 }
199
show_and_get_source(KODI_HANDLE kodiBase,const char * path_in,char ** path_out,bool allowNetworkShares,const char * additionalShare,const char * strType)200 bool Interface_GUIDialogFileBrowser::show_and_get_source(KODI_HANDLE kodiBase,
201 const char* path_in,
202 char** path_out,
203 bool allowNetworkShares,
204 const char* additionalShare,
205 const char* strType)
206 {
207 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
208 if (!addon)
209 {
210 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
211 return false;
212 }
213
214 if (!strType || !additionalShare || !path_in || !path_out)
215 {
216 CLog::Log(LOGERROR,
217 "Interface_GUIDialogFileBrowser::{} - invalid handler data (additionalShare='{}', "
218 "strType='{}', path_in='{}', path_out='{}') on addon '{}'",
219 __func__, static_cast<const void*>(additionalShare),
220 static_cast<const void*>(strType), static_cast<const void*>(path_in),
221 static_cast<void*>(path_out), addon->ID());
222 return false;
223 }
224
225 std::string strPath = path_in;
226
227 VECSOURCES vecShares;
228 if (additionalShare)
229 GetVECShares(vecShares, additionalShare, strPath);
230 bool bRet =
231 CGUIDialogFileBrowser::ShowAndGetSource(strPath, allowNetworkShares, &vecShares, strType);
232 if (bRet)
233 *path_out = strdup(strPath.c_str());
234 return bRet;
235 }
236
show_and_get_image(KODI_HANDLE kodiBase,const char * shares,const char * heading,const char * path_in,char ** path_out)237 bool Interface_GUIDialogFileBrowser::show_and_get_image(KODI_HANDLE kodiBase,
238 const char* shares,
239 const char* heading,
240 const char* path_in,
241 char** path_out)
242 {
243 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
244 if (!addon)
245 {
246 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
247 return false;
248 }
249
250 if (!shares || !heading)
251 {
252 CLog::Log(LOGERROR,
253 "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
254 "heading='{}') on addon '{}'",
255 __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
256 addon->ID());
257 return false;
258 }
259
260 std::string strPath = path_in;
261
262 VECSOURCES vecShares;
263 GetVECShares(vecShares, shares, strPath);
264 bool bRet = CGUIDialogFileBrowser::ShowAndGetImage(vecShares, heading, strPath);
265 if (bRet)
266 *path_out = strdup(strPath.c_str());
267 return bRet;
268 }
269
show_and_get_image_list(KODI_HANDLE kodiBase,const char * shares,const char * heading,char *** file_list,unsigned int * entries)270 bool Interface_GUIDialogFileBrowser::show_and_get_image_list(KODI_HANDLE kodiBase,
271 const char* shares,
272 const char* heading,
273 char*** file_list,
274 unsigned int* entries)
275 {
276 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
277 if (!addon)
278 {
279 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
280 return false;
281 }
282
283 if (!shares || !heading || !file_list || !entries)
284 {
285 CLog::Log(LOGERROR,
286 "Interface_GUIDialogFileBrowser::{} - invalid handler data (shares='{}', "
287 "heading='{}', file_list='{}', entries='{}') on addon '{}'",
288 __func__, static_cast<const void*>(shares), static_cast<const void*>(heading),
289 static_cast<void*>(file_list), static_cast<void*>(entries), addon->ID());
290 return false;
291 }
292
293 VECSOURCES vecShares;
294 GetVECShares(vecShares, shares, "");
295
296 std::vector<std::string> pathsInt;
297 bool bRet = CGUIDialogFileBrowser::ShowAndGetImageList(vecShares, heading, pathsInt);
298 if (bRet)
299 {
300 *entries = pathsInt.size();
301 *file_list = static_cast<char**>(malloc(*entries * sizeof(char*)));
302 for (unsigned int i = 0; i < *entries; ++i)
303 (*file_list)[i] = strdup(pathsInt[i].c_str());
304 }
305 else
306 *entries = 0;
307 return bRet;
308 }
309
clear_file_list(KODI_HANDLE kodiBase,char *** file_list,unsigned int entries)310 void Interface_GUIDialogFileBrowser::clear_file_list(KODI_HANDLE kodiBase,
311 char*** file_list,
312 unsigned int entries)
313 {
314 CAddonDll* addon = static_cast<CAddonDll*>(kodiBase);
315 if (!addon)
316 {
317 CLog::Log(LOGERROR, "Interface_GUIDialogFileBrowser::{} - invalid data", __func__);
318 return;
319 }
320
321 if (*file_list)
322 {
323 for (unsigned int i = 0; i < entries; ++i)
324 free((*file_list)[i]);
325 free(*file_list);
326 *file_list = nullptr;
327 }
328 else
329 {
330
331 CLog::Log(LOGERROR,
332 "Interface_GUIDialogFileBrowser::{} - invalid handler data (file_list='{}') on "
333 "addon '{}'",
334 __func__, static_cast<void*>(file_list), addon->ID());
335 }
336 }
337
GetVECShares(VECSOURCES & vecShares,const std::string & strShares,const std::string & strPath)338 void Interface_GUIDialogFileBrowser::GetVECShares(VECSOURCES& vecShares,
339 const std::string& strShares,
340 const std::string& strPath)
341 {
342 std::size_t found;
343 found = strShares.find("local");
344 if (found != std::string::npos)
345 CServiceBroker::GetMediaManager().GetLocalDrives(vecShares);
346 found = strShares.find("network");
347 if (found != std::string::npos)
348 CServiceBroker::GetMediaManager().GetNetworkLocations(vecShares);
349 found = strShares.find("removable");
350 if (found != std::string::npos)
351 CServiceBroker::GetMediaManager().GetRemovableDrives(vecShares);
352 found = strShares.find("programs");
353 if (found != std::string::npos)
354 {
355 VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("programs");
356 if (sources != nullptr)
357 vecShares.insert(vecShares.end(), sources->begin(), sources->end());
358 }
359 found = strShares.find("files");
360 if (found != std::string::npos)
361 {
362 VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("files");
363 if (sources != nullptr)
364 vecShares.insert(vecShares.end(), sources->begin(), sources->end());
365 }
366 found = strShares.find("music");
367 if (found != std::string::npos)
368 {
369 VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("music");
370 if (sources != nullptr)
371 vecShares.insert(vecShares.end(), sources->begin(), sources->end());
372 }
373 found = strShares.find("video");
374 if (found != std::string::npos)
375 {
376 VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("video");
377 if (sources != nullptr)
378 vecShares.insert(vecShares.end(), sources->begin(), sources->end());
379 }
380 found = strShares.find("pictures");
381 if (found != std::string::npos)
382 {
383 VECSOURCES* sources = CMediaSourceSettings::GetInstance().GetSources("pictures");
384 if (sources != nullptr)
385 vecShares.insert(vecShares.end(), sources->begin(), sources->end());
386 }
387
388 if (vecShares.empty())
389 {
390 CMediaSource share;
391 std::string basePath = strPath;
392 std::string tempPath;
393 while (URIUtils::GetParentPath(basePath, tempPath))
394 basePath = tempPath;
395 share.strPath = basePath;
396 // don't include the user details in the share name
397 CURL url(share.strPath);
398 share.strName = url.GetWithoutUserDetails();
399 vecShares.push_back(share);
400 }
401 }
402
403 } /* namespace ADDON */
404