summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h')
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h1622
1 files changed, 1138 insertions, 484 deletions
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
index 3bdc059..efd5de2 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
@@ -10,31 +10,162 @@
10#include "../AddonBase.h" 10#include "../AddonBase.h"
11#include "../Filesystem.h" 11#include "../Filesystem.h"
12 12
13#ifdef BUILD_KODI_ADDON 13#if !defined(_WIN32)
14#include "../IFileTypes.h" 14#include <sys/stat.h>
15#if !defined(__stat64)
16#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
17#define __stat64 stat
15#else 18#else
16#include "filesystem/IFileTypes.h" 19#define __stat64 stat64
17#include "PlatformDefs.h" 20#endif
21#endif
18#endif 22#endif
19 23
20namespace kodi { namespace addon { class CInstanceVFS; }} 24#ifdef __cplusplus
21
22extern "C" 25extern "C"
23{ 26{
24 27#endif /* __cplusplus */
28
29 //============================================================================
30 /// @ingroup cpp_kodi_addon_vfs_Defs
31 /// @brief **VFS add-on URL data**\n
32 /// This class is used to inform the addon of the desired wanted connection.
33 ///
34 /// Used on mostly all addon functions to identify related target.
35 ///
25 struct VFSURL 36 struct VFSURL
26 { 37 {
38 /// @brief Desired URL of the file system to be edited
39 ///
40 /// This includes all available parts of the access and is structured as
41 /// follows:
42 /// - <b>`<PROTOCOL>`://`<USERNAME>`:`<PASSWORD>``@``<HOSTNAME>`:`<PORT>`/`<FILENAME>`?`<OPTIONS>`</b>
27 const char* url; 43 const char* url;
44
45 /// @brief The associated domain name, which is optional and not available
46 /// in all cases.
28 const char* domain; 47 const char* domain;
48
49 /// @brief This includes the network address (e.g. `192.168.0.123`) or if
50 /// the addon refers to file packages the path to it
51 /// (e.g. `/home/by_me/MyPacket.rar`).
29 const char* hostname; 52 const char* hostname;
53
54 /// @brief With this variable the desired path to a folder or file within
55 /// the hostname is given (e.g. `storage/videos/00001.ts`).
30 const char* filename; 56 const char* filename;
57
58 /// @brief [Networking port](https://en.wikipedia.org/wiki/Port_(computer_networking))
59 /// to use for protocol.
31 unsigned int port; 60 unsigned int port;
61
62 /// @brief Special options on opened URL, this can e.g. on RAR packages
63 /// <b>`?flags=8&nextvalue=123`</b> to inform about to not cache a read.
64 ///
65 /// Available options from Kodi:
66 /// | Value: | Description:
67 /// |-----------|-------------------
68 /// | flags=8 | Used on RAR packages so that no data is cached from the requested source.
69 /// | cache=no | Used on ZIP packages so that no data from the requested source is stored in the cache. However, this is currently not available from addons!
70 ///
71 /// In addition, other addons can use the URLs given by them to give options
72 /// that fit the respective VFS addon and allow special operations.
73 ///
74 /// @note This procedure is not yet standardized and is currently not
75 /// exactly available which are handed over.
32 const char* options; 76 const char* options;
77
78 /// @brief Desired username.
33 const char* username; 79 const char* username;
80
81 /// @brief Desired password.
34 const char* password; 82 const char* password;
83
84 /// @brief The complete URL is passed on here, but the user name and
85 /// password are not shown and only appear to there as `USERNAME:PASSWORD`.
86 ///
87 /// As example <b>`sftp://USERNAME:PASSWORD@192.168.178.123/storage/videos/00001.ts`</b>.
35 const char* redacted; 88 const char* redacted;
89
90 /// @brief The name which is taken as the basis by source and would be first
91 /// in folder view.
92 ///
93 /// As example on <b>`sftp://dudu:isprivate@192.168.178.123/storage/videos/00001.ts`</b>
94 /// becomes then <b>`storage`</b> used here.
36 const char* sharename; 95 const char* sharename;
96
97 /// @brief Protocol name used on this stream, e.g. <b>`sftp`</b>.
98 const char* protocol;
37 }; 99 };
100 //----------------------------------------------------------------------------
101
102 //============================================================================
103 /// @ingroup cpp_kodi_addon_vfs_Defs
104 /// @brief <b>In/out value which is queried at @ref kodi::addon::CInstanceVFS::IoControl.</b>\n
105 /// This declares the requested value on the addon, this gets or has to
106 /// transfer data depending on the value.
107 enum VFS_IOCTRL
108 {
109 /// @brief For cases where not supported control becomes asked.
110 ///
111 /// @note Should normally not given to addon.
112 VFS_IOCTRL_INVALID = 0,
113
114 /// @brief @ref VFS_IOCTRL_NATIVE_DATA structure, containing what should be
115 /// passed to native ioctrl.
116 VFS_IOCTRL_NATIVE = 1,
117
118 /// @brief To check seek is possible.
119 ///
120 //// Return 0 if known not to work, 1 if it should work on related calls.
121 VFS_IOCTRL_SEEK_POSSIBLE = 2,
122
123 /// @brief @ref VFS_IOCTRL_CACHE_STATUS_DATA structure structure on related call
124 VFS_IOCTRL_CACHE_STATUS = 3,
125
126 /// @brief Unsigned int with speed limit for caching in bytes per second
127 VFS_IOCTRL_CACHE_SETRATE = 4,
128
129 /// @brief Enable/disable retry within the protocol handler (if supported)
130 VFS_IOCTRL_SET_RETRY = 16,
131 };
132 //----------------------------------------------------------------------------
133
134 //============================================================================
135 /// @ingroup cpp_kodi_addon_vfs_Defs
136 /// @brief <b>Structure used in @ref kodi::addon::CInstanceVFS::IoControl
137 /// if question value for @ref VFS_IOCTRL_NATIVE is set</b>\n
138 /// With this structure, data is transmitted to the Kodi addon.
139 ///
140 /// This corresponds to POSIX systems with regard to [ioctl](https://en.wikipedia.org/wiki/Ioctl)
141 /// data (emulated with Windows).
142 struct VFS_IOCTRL_NATIVE_DATA
143 {
144 unsigned long int request;
145 void* param;
146 };
147 //----------------------------------------------------------------------------
148
149 //============================================================================
150 /// @ingroup cpp_kodi_addon_vfs_Defs
151 /// @brief <b>Structure used in @ref kodi::addon::CInstanceVFS::IoControl
152 /// if question value for @ref VFS_IOCTRL_CACHE_STATUS is set</b>\n
153 /// This data is filled by the addon and returned to Kodi
154 struct VFS_IOCTRL_CACHE_STATUS_DATA
155 {
156 /// @brief Number of bytes cached forward of current position.
157 uint64_t forward;
158
159 /// @brief Maximum number of bytes per second cache is allowed to fill.
160 unsigned int maxrate;
161
162 /// @brief Average read rate from source file since last position change.
163 unsigned int currate;
164
165 /// @brief Cache low speed condition detected?
166 bool lowspeed;
167 };
168 //----------------------------------------------------------------------------
38 169
39 typedef struct VFSGetDirectoryCallbacks /* internal */ 170 typedef struct VFSGetDirectoryCallbacks /* internal */
40 { 171 {
@@ -57,555 +188,1078 @@ extern "C"
57 struct AddonInstance_VFSEntry; 188 struct AddonInstance_VFSEntry;
58 typedef struct KodiToAddonFuncTable_VFSEntry /* internal */ 189 typedef struct KodiToAddonFuncTable_VFSEntry /* internal */
59 { 190 {
60 kodi::addon::CInstanceVFS* addonInstance; 191 KODI_HANDLE addonInstance;
61 192
62 void* (__cdecl* open) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 193 void*(__cdecl* open)(const struct AddonInstance_VFSEntry* instance, const struct VFSURL* url);
63 void* (__cdecl* open_for_write) (const AddonInstance_VFSEntry* instance, const VFSURL* url, bool overwrite); 194 void*(__cdecl* open_for_write)(const struct AddonInstance_VFSEntry* instance,
64 ssize_t (__cdecl* read) (const AddonInstance_VFSEntry* instance, void* context, void* buffer, size_t buf_size); 195 const struct VFSURL* url,
65 ssize_t (__cdecl* write) (const AddonInstance_VFSEntry* instance, void* context, const void* buffer, size_t buf_size); 196 bool overwrite);
66 int64_t (__cdecl* seek) (const AddonInstance_VFSEntry* instance, void* context, int64_t position, int whence); 197 ssize_t(__cdecl* read)(const struct AddonInstance_VFSEntry* instance,
67 int (__cdecl* truncate) (const AddonInstance_VFSEntry* instance, void* context, int64_t size); 198 void* context,
68 int64_t (__cdecl* get_length) (const AddonInstance_VFSEntry* instance, void* context); 199 void* buffer,
69 int64_t (__cdecl* get_position) (const AddonInstance_VFSEntry* instance, void* context); 200 size_t buf_size);
70 int (__cdecl* get_chunk_size) (const AddonInstance_VFSEntry* instance, void* context); 201 ssize_t(__cdecl* write)(const struct AddonInstance_VFSEntry* instance,
71 int (__cdecl* io_control) (const AddonInstance_VFSEntry* instance, void* context, XFILE::EIoControl request, void* param); 202 void* context,
72 int (__cdecl* stat) (const AddonInstance_VFSEntry* instance, const VFSURL* url, struct __stat64* buffer); 203 const void* buffer,
73 bool (__cdecl* close) (const AddonInstance_VFSEntry* instance, void* context); 204 size_t buf_size);
74 bool (__cdecl* exists) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 205 int64_t(__cdecl* seek)(const struct AddonInstance_VFSEntry* instance,
75 void (__cdecl* clear_out_idle) (const AddonInstance_VFSEntry* instance); 206 void* context,
76 void (__cdecl* disconnect_all) (const AddonInstance_VFSEntry* instance); 207 int64_t position,
77 bool (__cdecl* delete_it) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 208 int whence);
78 bool (__cdecl* rename) (const AddonInstance_VFSEntry* instance, const VFSURL* url, const VFSURL* url2); 209 int(__cdecl* truncate)(const struct AddonInstance_VFSEntry* instance,
79 bool (__cdecl* directory_exists) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 210 void* context,
80 bool (__cdecl* remove_directory) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 211 int64_t size);
81 bool (__cdecl* create_directory) (const AddonInstance_VFSEntry* instance, const VFSURL* url); 212 int64_t(__cdecl* get_length)(const struct AddonInstance_VFSEntry* instance, void* context);
82 bool (__cdecl* get_directory) (const AddonInstance_VFSEntry* instance, 213 int64_t(__cdecl* get_position)(const struct AddonInstance_VFSEntry* instance, void* context);
83 const VFSURL* url, 214 int(__cdecl* get_chunk_size)(const struct AddonInstance_VFSEntry* instance, void* context);
84 VFSDirEntry** entries, 215 int(__cdecl* io_control)(const struct AddonInstance_VFSEntry* instance,
216 void* context,
217 enum VFS_IOCTRL request,
218 void* param);
219 int(__cdecl* stat)(const struct AddonInstance_VFSEntry* instance,
220 const struct VFSURL* url,
221 struct __stat64* buffer);
222 bool(__cdecl* close)(const struct AddonInstance_VFSEntry* instance, void* context);
223 bool(__cdecl* exists)(const struct AddonInstance_VFSEntry* instance, const struct VFSURL* url);
224 void(__cdecl* clear_out_idle)(const struct AddonInstance_VFSEntry* instance);
225 void(__cdecl* disconnect_all)(const struct AddonInstance_VFSEntry* instance);
226 bool(__cdecl* delete_it)(const struct AddonInstance_VFSEntry* instance,
227 const struct VFSURL* url);
228 bool(__cdecl* rename)(const struct AddonInstance_VFSEntry* instance,
229 const struct VFSURL* url,
230 const struct VFSURL* url2);
231 bool(__cdecl* directory_exists)(const struct AddonInstance_VFSEntry* instance,
232 const struct VFSURL* url);
233 bool(__cdecl* remove_directory)(const struct AddonInstance_VFSEntry* instance,
234 const struct VFSURL* url);
235 bool(__cdecl* create_directory)(const struct AddonInstance_VFSEntry* instance,
236 const struct VFSURL* url);
237 bool(__cdecl* get_directory)(const struct AddonInstance_VFSEntry* instance,
238 const struct VFSURL* url,
239 struct VFSDirEntry** entries,
240 int* num_entries,
241 VFSGetDirectoryCallbacks* callbacks);
242 bool(__cdecl* contains_files)(const struct AddonInstance_VFSEntry* instance,
243 const struct VFSURL* url,
244 struct VFSDirEntry** entries,
85 int* num_entries, 245 int* num_entries,
86 VFSGetDirectoryCallbacks* callbacks); 246 char* rootpath);
87 bool (__cdecl* contains_files) (const AddonInstance_VFSEntry* instance, 247 void(__cdecl* free_directory)(const struct AddonInstance_VFSEntry* instance,
88 const VFSURL* url, 248 struct VFSDirEntry* entries,
89 VFSDirEntry** entries, 249 int num_entries);
90 int* num_entries,
91 char* rootpath);
92 void (__cdecl* free_directory) (const AddonInstance_VFSEntry* instance, VFSDirEntry* entries, int num_entries);
93 } KodiToAddonFuncTable_VFSEntry; 250 } KodiToAddonFuncTable_VFSEntry;
94 251
95 typedef struct AddonInstance_VFSEntry /* internal */ 252 typedef struct AddonInstance_VFSEntry /* internal */
96 { 253 {
97 AddonProps_VFSEntry props; 254 AddonProps_VFSEntry* props;
98 AddonToKodiFuncTable_VFSEntry toKodi; 255 AddonToKodiFuncTable_VFSEntry* toKodi;
99 KodiToAddonFuncTable_VFSEntry toAddon; 256 KodiToAddonFuncTable_VFSEntry* toAddon;
100 } AddonInstance_VFSEntry; 257 } AddonInstance_VFSEntry;
101 258
259#ifdef __cplusplus
102} /* extern "C" */ 260} /* extern "C" */
103 261
104namespace kodi 262namespace kodi
105{ 263{
106namespace addon 264namespace addon
107{ 265{
108 class CInstanceVFS : public IAddonInstance 266
267//##############################################################################
268/// @defgroup cpp_kodi_addon_vfs_Defs Definitions, structures and enumerators
269/// \ingroup cpp_kodi_addon_vfs
270/// @brief **VFS add-on general variables**
271///
272/// Used to exchange the available options between Kodi and addon.
273///
274///
275
276//==============================================================================
277///
278/// \addtogroup cpp_kodi_addon_vfs
279/// @brief \cpp_class{ kodi::addon::CInstanceVFS }
280/// **Virtual Filesystem (VFS) add-on instance**
281///
282/// This instance type is used to allow Kodi various additional file system
283/// types. Be it a special file system, a compressed package or a system
284/// available over the network, everything is possible with it.
285///
286/// This usage can be requested under various conditions, for example explicitly
287/// by another addon, by a Mimetype protocol defined in <b>`addon.xml`</b> or supported
288/// file extensions.
289///
290/// Include the header @ref VFS.h "#include <kodi/addon-instance/VFS.h>"
291/// to use this class.
292///
293/// ----------------------------------------------------------------------------
294///
295/// Here is an example of what the <b>`addon.xml.in`</b> would look like for an VFS addon:
296///
297/// ~~~~~~~~~~~~~{.xml}
298/// <?xml version="1.0" encoding="UTF-8"?>
299/// <addon
300/// id="vfs.myspecialnamefor"
301/// version="1.0.0"
302/// name="My VFS addon"
303/// provider-name="Your Name">
304/// <requires>@ADDON_DEPENDS@</requires>
305/// <extension
306/// point="kodi.vfs"
307/// protocols="myprot"
308/// extensions=".abc|.def"
309/// files="true"
310/// filedirectories="true"
311/// directories="true"
312/// encodedhostname="true"
313/// supportDialog="true"
314/// supportPath="true"
315/// supportUsername="true"
316/// supportPassword="true"
317/// supportPort="true"
318/// supportBrowsing="true"
319/// supportWrite="true"
320/// defaultPort="1234"
321/// label="30000"
322/// zeroconf="your_special_zeroconf_allowed_identifier"
323/// library_@PLATFORM@="@LIBRARY_FILENAME@"/>
324/// <extension point="xbmc.addon.metadata">
325/// <summary lang="en_GB">My VFS addon summary</summary>
326/// <description lang="en_GB">My VFS description</description>
327/// <platform>@PLATFORM@</platform>
328/// </extension>
329/// </addon>
330/// ~~~~~~~~~~~~~
331///
332/// @note Regarding boolean values with "false", these can also be omitted,
333/// since this would be the default.
334///
335///
336/// ### Standard values that can be declared for processing in `addon.xml`.
337///
338/// These values are used by Kodi to identify associated streams and file
339/// extensions and then to select the associated addon.
340///
341/// \table_start
342/// \table_h3{ Labels, Type, Description }
343/// \table_row3{ <b>`point`</b>,
344/// \anchor cpp_kodi_addon_vfs_point
345/// string,
346/// The identification of the addon instance to VFS is mandatory <b>`kodi.vfs`</b>.
347/// In addition\, the instance declared in the first <b>`<extension ... />`</b> is also the main type of addon.
348/// }
349/// \table_row3{ <b>`defaultPort`</b>,
350/// \anchor cpp_kodi_addon_vfs_defaultPort
351/// integer,
352/// Default [networking port](https://en.wikipedia.org/wiki/Port_(computer_networking))
353/// to use for protocol.
354/// }
355/// \table_row3{ <b>`directories`</b>,
356/// \anchor cpp_kodi_addon_vfs_directories
357/// boolean,
358/// VFS entry can list directories.
359/// }
360/// \table_row3{ <b>`extensions`</b>,
361/// \anchor cpp_kodi_addon_vfs_extensions
362/// string,
363/// Extensions for VFS entry.\n
364/// It is possible to declare several using <b>`|`</b>\, e.g. <b>`.abc|.def|.ghi`</b>.
365/// }
366/// \table_row3{ <b>`encodedhostname`</b>,
367/// \anchor cpp_kodi_addon_vfs_encodedhostname
368/// boolean,
369/// URL protocol from add-ons use encoded hostnames.
370/// }
371/// \table_row3{ <b>`filedirectories`</b>,
372/// \anchor cpp_kodi_addon_vfs_filedirectories
373/// boolean,
374/// VFS entry contains file directories.
375/// }
376/// \table_row3{ <b>`files`</b>,
377/// \anchor cpp_kodi_addon_vfs_directories
378/// boolean,
379/// Set to declare that VFS provides files.
380/// }
381/// \table_row3{ <b>`protocols`</b>,
382/// \anchor cpp_kodi_addon_vfs_protocols
383/// boolean,
384/// Protocols for VFS entry.\n
385/// It is possible to declare several using <b>`|`</b>\, e.g. <b>`myprot1|myprot2`</b>.\n
386/// @note This field also used to show on GUI\, see <b>`supportBrowsing`</b> below about <b>*2:</b>.
387/// When used there\, however\, only a **single** protocol is possible!
388/// }
389/// \table_row3{ <b>`supportWrite`</b>,
390/// \anchor cpp_kodi_addon_vfs_supportWrite
391/// boolean,
392/// Protocol supports write operations.
393/// }
394/// \table_row3{ <b>`zeroconf`</b>,
395/// \anchor cpp_kodi_addon_vfs_zeroconf
396/// string,
397/// [Zero conf](https://en.wikipedia.org/wiki/Zero-configuration_networking) announce string for VFS protocol.
398/// }
399/// \table_row3{ <b>`library_@PLATFORM@`</b>,
400/// \anchor cpp_kodi_addon_vfs_library
401/// string,
402/// The runtime library used for the addon. This is usually declared by `cmake` and correctly displayed in the translated <b>`addon.xml`</b>.
403/// }
404/// \table_end
405///
406///
407/// ### User selectable parts of the addon.
408///
409/// The following table describes the values that can be defined by <b>`addon.xml`</b>
410/// and which part they relate to for user input.
411///
412/// \table_start
413/// \table_h3{ Labels, Type, Description }
414/// \table_row3{ <b>`supportBrowsing`</b>,
415/// \anchor cpp_kodi_addon_vfs_protocol_supportBrowsing
416/// boolean,
417/// Protocol supports server browsing. Used to open related sources by users in the window.\n\n
418/// | Associated places in Kodi: |
419/// | :---- |
420/// | \image html cpp_kodi_addon_vfs_protocol_1.png |
421/// <br>
422/// <b>*1:</b> The entry in the menu represented by this option corresponds to the text given with <b>`label`</b>.
423/// When the button is pressed\, @ref CInstanceVFS::GetDirectory is called on the add-on to get its content.\n
424/// <b>*2:</b> Protocol name of the stream defined with <b>`protocols`</b> in xml.\n
425/// @remark See also <b>`supportDialog`</b> about <b>*3:</b>.
426/// }
427/// \table_row3{ <b>`supportDialog`</b>,
428/// \anchor cpp_kodi_addon_vfs_protocol_supportDialog
429/// boolean,
430/// To point out that Kodi assigns a dialog to this VFS in order to compare it with other values e.g. query supportPassword in it.\n
431/// This will be available when adding sources in Kodi under <b>"Add network location..."</b>.\n\n
432/// | Associated places in Kodi: |
433/// | :---- |
434/// | \image html cpp_kodi_addon_vfs_protocol_2.png |
435/// <br>
436/// <b>*1:</b> Field for selecting the VFS handler\, the addon will be available if <b>`supportDialog`</b> is set to <b>`true`</b>.\n
437/// <b>*2:</b> To set the associated server address. **Note:** *This field is always activated and cannot be changed by the addon.*\n
438/// <b>*3:</b> If <b>`supportBrowsing`</b> is set to <b>`true`</b>\, the button for opening a file selection dialog is given here too\, as in the file window.\n
439/// <b>*4:</b> This field is available if <b>`supportPath`</b> is set to <b>`true`</b>.\n
440/// <b>*5:</b> To edit the connection port. This field is available if <b>`supportPort`</b> is set to <b>`true`</b>.\n
441/// <b>*6:</b> This sets the required username and is available when <b>`supportUsername`</b> is set to <b>`true`</b>.\n
442/// <b>*7:</b> This sets the required password and is available when <b>`supportPassword`</b> is set to <b>`true`</b>.
443/// }
444/// \table_row3{ <b>`supportPath`</b>,
445/// \anchor cpp_kodi_addon_vfs_protocol_supportPath
446/// boolean,
447/// Protocol has path in addition to server name (see <b>`supportDialog`</b> about <b>*4:</b>).
448/// }
449/// \table_row3{ <b>`supportPort`</b>,
450/// \anchor cpp_kodi_addon_vfs_protocol_supportPort
451/// boolean,
452/// Protocol supports port customization (see <b>`supportDialog`</b> about <b>*5:</b>).
453/// }
454/// \table_row3{ <b>`supportUsername`</b>,
455/// \anchor cpp_kodi_addon_vfs_protocol_supportUsername
456/// boolean,
457/// Protocol uses logins (see <b>`supportDialog`</b> about <b>*6:</b>).
458/// }
459/// \table_row3{ <b>`supportPassword`</b>,
460/// \anchor cpp_kodi_addon_vfs_protocol_supportPassword
461/// boolean,
462/// Protocol supports passwords (see <b>`supportDialog`</b> about <b>*7:</b>).
463/// }
464/// \table_row3{ <b>`protocols`</b>,
465/// \anchor cpp_kodi_addon_vfs_protocol_protocols
466/// string,
467/// Protocols for VFS entry.
468/// @note This field is not editable and only used on GUI to show his name\, see <b>`supportBrowsing`</b> about <b>*2:</b>
469/// }
470/// \table_row3{ <b>`label`</b>,
471/// \anchor cpp_kodi_addon_vfs_protocol_label
472/// integer,
473/// The text identification number used in Kodi for display in the menu at <b>`supportDialog`</b>
474/// as a selection option and at <b>`supportBrowsing`</b> (see his image reference <b>*1</b>) as a menu entry.\n
475/// This can be a text identifier in Kodi or from addon.\n
476/// @remark For addon within <b>30000</b>-<b>30999</b> or <b>32000</b>-<b>32999</b>.
477/// }
478/// \table_end
479///
480/// @remark For more detailed description of the <b>`addon.xml`</b>, see also https://kodi.wiki/view/Addon.xml.
481///
482///
483/// --------------------------------------------------------------------------
484///
485///
486/// **Example:**
487///
488/// ~~~~~~~~~~~~~{.cpp}
489/// #include <kodi/addon-instance/VFS.h>
490///
491/// class CMyVFS : public kodi::addon::CInstanceVFS
492/// {
493/// public:
494/// CMyVFS(KODI_HANDLE instance, const std::string& kodiVersion);
495///
496/// // Add all your required functions, the most CInstanceVFS functions of
497/// // must be included to have addon working correctly.
498/// ...
499/// };
500///
501/// CMyVFS::CMyVFS(KODI_HANDLE instance, const std::string& kodiVersion)
502/// : CInstanceVFS(instance, kodiVersion)
503/// {
504/// ...
505/// }
506///
507/// ...
508///
509/// /*----------------------------------------------------------------------*/
510///
511/// class CMyAddon : public kodi::addon::CAddonBase
512/// {
513/// public:
514/// CMyAddon() { }
515/// ADDON_STATUS CreateInstance(int instanceType,
516/// const std::string& instanceID,
517/// KODI_HANDLE instance,
518/// const std::string& version,
519/// KODI_HANDLE& addonInstance) override;
520/// };
521///
522/// // If you use only one instance in your add-on, can be instanceType and
523/// // instanceID ignored
524/// ADDON_STATUS CMyAddon::CreateInstance(int instanceType,
525/// const std::string& instanceID,
526/// KODI_HANDLE instance,
527/// const std::string& version,
528/// KODI_HANDLE& addonInstance)
529/// {
530/// if (instanceType == ADDON_INSTANCE_VFS)
531/// {
532/// kodi::Log(ADDON_LOG_NOTICE, "Creating my VFS instance");
533/// addonInstance = new CMyVFS(instance, version);
534/// return ADDON_STATUS_OK;
535/// }
536/// else if (...)
537/// {
538/// ...
539/// }
540/// return ADDON_STATUS_UNKNOWN;
541/// }
542///
543/// ADDONCREATOR(CMyAddon)
544/// ~~~~~~~~~~~~~
545///
546/// The destruction of the example class `CMyVFS` is called from
547/// Kodi's header. Manually deleting the add-on instance is not required.
548///
549//----------------------------------------------------------------------------
550class ATTRIBUTE_HIDDEN CInstanceVFS : public IAddonInstance
551{
552public:
553 //==========================================================================
554 ///
555 /// @ingroup cpp_kodi_addon_vfs
556 /// @brief VFS class constructor used to support multiple instance
557 /// types
558 ///
559 /// @param[in] instance The instance value given to
560 /// <b>`kodi::addon::CAddonBase::CreateInstance(...)`</b>.
561 /// @param[in] kodiVersion [opt] given from Kodi by @ref CAddonBase::CreateInstance
562 /// to identify his instance API version
563 ///
564 /// @note Instance path as a single is not supported by this type. It must
565 /// ensure that it can be called up several times.
566 ///
567 /// @warning Only use `instance` from the @ref CAddonBase::CreateInstance or
568 /// @ref CAddonBase::CreateInstance call.
569 ///
570 explicit CInstanceVFS(KODI_HANDLE instance, const std::string& kodiVersion = "")
571 : IAddonInstance(ADDON_INSTANCE_VFS,
572 !kodiVersion.empty() ? kodiVersion : GetKodiTypeVersion(ADDON_INSTANCE_VFS))
573 {
574 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
575 throw std::logic_error("kodi::addon::CInstanceVFS: Creation of multiple together with single "
576 "instance way is not allowed!");
577
578 SetAddonStruct(instance);
579 }
580 //--------------------------------------------------------------------------
581
582 //==========================================================================
583 ///
584 /// @ingroup cpp_kodi_addon_vfs
585 /// @brief Destructor
586 ///
587 ~CInstanceVFS() override = default;
588 //--------------------------------------------------------------------------
589
590 //==========================================================================
591 ///
592 /// @defgroup cpp_kodi_addon_vfs_general 1. General access functions
593 /// @ingroup cpp_kodi_addon_vfs
594 /// @brief **General access functions**
595 ///
596 /// This functions which are intended for getting folders, editing storage
597 /// locations and file system queries.
598 ///
599
600 //==========================================================================
601 ///
602 /// @defgroup cpp_kodi_addon_vfs_filecontrol 2. File editing functions
603 /// @ingroup cpp_kodi_addon_vfs
604 /// @brief **File editing functions.**
605 ///
606 /// This value represents the addon-side handlers and to be able to identify
607 /// his own parts in the event of further access.
608 ///
609
610 //@{
611 //==========================================================================
612 ///
613 /// @ingroup cpp_kodi_addon_vfs_filecontrol
614 /// @brief Open a file for input
615 ///
616 /// @param[in] url The URL of the file
617 /// @return Context for the opened file
618 virtual void* Open(const VFSURL& url) { return nullptr; }
619
620 //==========================================================================
621 ///
622 /// @ingroup cpp_kodi_addon_vfs_filecontrol
623 /// @brief Open a file for output
624 ///
625 /// @param[in] url The URL of the file
626 /// @param[in] overWrite Whether or not to overwrite an existing file
627 /// @return Context for the opened file
628 ///
629 virtual void* OpenForWrite(const VFSURL& url, bool overWrite) { return nullptr; }
630 //--------------------------------------------------------------------------
631
632 //==========================================================================
633 ///
634 /// @ingroup cpp_kodi_addon_vfs_filecontrol
635 /// @brief Close a file
636 ///
637 /// @param[in] context The context of the file
638 /// @return True on success, false on failure
639 ///
640 virtual bool Close(void* context) { return false; }
641 //--------------------------------------------------------------------------
642
643 //==========================================================================
644 ///
645 /// @ingroup cpp_kodi_addon_vfs_filecontrol
646 /// @brief Read from a file
647 ///
648 /// @param[in] context The context of the file
649 /// @param[out] buffer The buffer to read data into
650 /// @param[in] uiBufSize Number of bytes to read
651 /// @return Number of bytes read
652 ///
653 virtual ssize_t Read(void* context, void* buffer, size_t uiBufSize) { return -1; }
654 //--------------------------------------------------------------------------
655
656 //==========================================================================
657 ///
658 /// @ingroup cpp_kodi_addon_vfs_filecontrol
659 /// @brief Write to a file
660 ///
661 /// @param[in] context The context of the file
662 /// @param[in] buffer The buffer to read data from
663 /// @param[in] uiBufSize Number of bytes to write
664 /// @return Number of bytes written
665 ///
666 virtual ssize_t Write(void* context, const void* buffer, size_t uiBufSize) { return -1; }
667 //--------------------------------------------------------------------------
668
669 //==========================================================================
670 ///
671 /// @ingroup cpp_kodi_addon_vfs_filecontrol
672 /// @brief Seek in a file
673 ///
674 /// @param[in] context The context of the file
675 /// @param[in] position The position to seek to
676 /// @param[in] whence Position in file 'position' is relative to (SEEK_CUR, SEEK_SET, SEEK_END)
677 /// @return Offset in file after seek
678 ///
679 virtual int64_t Seek(void* context, int64_t position, int whence) { return -1; }
680 //--------------------------------------------------------------------------
681
682 //==========================================================================
683 ///
684 /// @ingroup cpp_kodi_addon_vfs_filecontrol
685 /// @brief Truncate a file
686 ///
687 /// @param[in] context The context of the file
688 /// @param[in] size The size to truncate the file to
689 /// @return 0 on success, -1 on error
690 ///
691 virtual int Truncate(void* context, int64_t size) { return -1; }
692 //--------------------------------------------------------------------------
693
694 //==========================================================================
695 ///
696 /// @ingroup cpp_kodi_addon_vfs_filecontrol
697 /// @brief Get total size of a file
698 ///
699 /// @param[in] context The context of the file
700 /// @return Total file size
701 ///
702 virtual int64_t GetLength(void* context) { return 0; }
703 //--------------------------------------------------------------------------
704
705 //==========================================================================
706 ///
707 /// @ingroup cpp_kodi_addon_vfs_filecontrol
708 /// @brief Get current position in a file
709 ///
710 /// @param[in] context The context of the file
711 /// @return Current position
712 ///
713 virtual int64_t GetPosition(void* context) { return 0; }
714 //--------------------------------------------------------------------------
715
716 //==========================================================================
717 ///
718 /// @ingroup cpp_kodi_addon_vfs_filecontrol
719 /// @brief Get chunk size of a file
720 ///
721 /// @param[in] context The context of the file
722 /// @return Chunk size
723 ///
724 virtual int GetChunkSize(void* context) { return 1; }
725 //--------------------------------------------------------------------------
726
727 //==========================================================================
728 ///
729 /// @ingroup cpp_kodi_addon_vfs_filecontrol
730 /// @brief Perform an IO-control on the file
731 ///
732 /// @param[in] context The context of the file
733 /// @param[in] request The requested IO-control
734 /// @param[in] param Parameter attached to the IO-control
735 /// @return -1 on error, >= 0 on success
736 ///
737 virtual int IoControl(void* context, VFS_IOCTRL request, void* param) { return -1; }
738 //--------------------------------------------------------------------------
739 //@}
740
741 //@{
742 //==========================================================================
743 ///
744 /// @ingroup cpp_kodi_addon_vfs_general
745 /// @brief Stat a file
746 ///
747 /// @param[in] url The URL of the file
748 /// @param[in] buffer The buffer to store results in
749 /// @return -1 on error, 0 otherwise
750 ///
751 virtual int Stat(const VFSURL& url, struct __stat64* buffer) { return 0; }
752 //--------------------------------------------------------------------------
753
754 //==========================================================================
755 ///
756 /// @ingroup cpp_kodi_addon_vfs_general
757 /// @brief Check for file existence
758 ///
759 /// @param[in] url The URL of the file
760 /// @return True if file exists, false otherwise
761 ///
762 virtual bool Exists(const VFSURL& url) { return false; }
763 //--------------------------------------------------------------------------
764
765 //==========================================================================
766 ///
767 /// @ingroup cpp_kodi_addon_vfs_general
768 /// @brief Clear out any idle connections
769 ///
770 virtual void ClearOutIdle() {}
771 //--------------------------------------------------------------------------
772
773 //==========================================================================
774 ///
775 /// @ingroup cpp_kodi_addon_vfs_general
776 /// @brief Disconnect all connections
777 ///
778 virtual void DisconnectAll() {}
779 //--------------------------------------------------------------------------
780
781 //==========================================================================
782 ///
783 /// @ingroup cpp_kodi_addon_vfs_general
784 /// @brief Delete a file
785 ///
786 /// @param[in] url The URL of the file
787 /// @return True if deletion was successful, false otherwise
788 ///
789 virtual bool Delete(const VFSURL& url) { return false; }
790 //--------------------------------------------------------------------------
791
792 //==========================================================================
793 ///
794 /// @ingroup cpp_kodi_addon_vfs_general
795 /// @brief Rename a file
796 ///
797 /// @param[in] url The URL of the source file
798 /// @param[in] url2 The URL of the destination file
799 /// @return True if deletion was successful, false otherwise
800 ///
801 virtual bool Rename(const VFSURL& url, const VFSURL& url2) { return false; }
802 //--------------------------------------------------------------------------
803
804 //==========================================================================
805 ///
806 /// @ingroup cpp_kodi_addon_vfs_general
807 /// @brief Check for directory existence
808 ///
809 /// @param[in] url The URL of the file
810 /// @return True if directory exists, false otherwise
811 ///
812 virtual bool DirectoryExists(const VFSURL& url) { return false; }
813 //--------------------------------------------------------------------------
814
815 //==========================================================================
816 ///
817 /// @ingroup cpp_kodi_addon_vfs_general
818 /// @brief Remove a directory
819 ///
820 /// @param[in] url The URL of the directory
821 /// @return True if removal was successful, false otherwise
822 ///
823 virtual bool RemoveDirectory(const VFSURL& url) { return false; }
824 //--------------------------------------------------------------------------
825
826 //==========================================================================
827 ///
828 /// @ingroup cpp_kodi_addon_vfs_general
829 /// @brief Create a directory
830 ///
831 /// @param[in] url The URL of the file
832 /// @return True if creation was successful, false otherwise
833 ///
834 virtual bool CreateDirectory(const VFSURL& url) { return false; }
835 //--------------------------------------------------------------------------
836
837 //==========================================================================
838 ///
839 /// @defgroup cpp_kodi_addon_vfs_general_cb_GetDirectory **Callbacks GetDirectory()**
840 /// @ingroup cpp_kodi_addon_vfs_general
841 /// @brief Callback functions on GetDirectory()
842 ///
843 /// This functions becomes available during call of GetDirectory() from
844 /// Kodi.
845 ///
846 /// If GetDirectory() returns false becomes the parts from here used on
847 /// next call of the function.
848 ///
849 /// **Example:**
850 /// ~~~~~~~~~~~~~{.cpp}
851 ///
852 /// #include <kodi/addon-instance/VFS.h>
853 ///
854 /// ...
855 ///
856 /// bool CMyVFS::GetDirectory(const VFSURL& url, std::vector<kodi::vfs::CDirEntry>& items, CVFSCallbacks callbacks)
857 /// {
858 /// std::string neededString;
859 /// callbacks.GetKeyboardInput("Test", neededString, true);
860 /// if (neededString.empty())
861 /// return false;
862 ///
863 /// // Do the work
864 /// ...
865 /// return true;
866 /// }
867 /// ~~~~~~~~~~~~~
868 ///
869 class CVFSCallbacks
109 { 870 {
110 public: 871 public:
111 explicit CInstanceVFS(KODI_HANDLE instance) 872 /// @ingroup cpp_kodi_addon_vfs_general_cb_GetDirectory
112 : IAddonInstance(ADDON_INSTANCE_VFS) 873 /// @brief Require keyboard input
113 {
114 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
115 throw std::logic_error("kodi::addon::CInstanceVFS: Creation of multiple together with single instance way is not allowed!");
116
117 SetAddonStruct(instance);
118 }
119
120 ~CInstanceVFS() override = default;
121
122 /// @brief Open a file for input
123 ///
124 /// @param[in] url The URL of the file
125 /// @return Context for the opened file
126 virtual void* Open(const VFSURL& url) { return nullptr; }
127
128 /// @brief Open a file for output
129 ///
130 /// @param[in] url The URL of the file
131 /// @param[in] overWrite Whether or not to overwrite an existing file
132 /// @return Context for the opened file
133 ///
134 virtual void* OpenForWrite(const VFSURL& url, bool overWrite) { return nullptr; }
135
136 /// @brief Read from a file
137 ///
138 /// @param[in] context The context of the file
139 /// @param[out] buffer The buffer to read data into
140 /// @param[in] uiBufSize Number of bytes to read
141 /// @return Number of bytes read
142 ///
143 virtual ssize_t Read(void* context, void* buffer, size_t uiBufSize) { return -1; }
144
145 /// @brief Write to a file
146 ///
147 /// @param[in] context The context of the file
148 /// @param[in] buffer The buffer to read data from
149 /// @param[in] uiBufSize Number of bytes to write
150 /// @return Number of bytes written
151 ///
152 virtual ssize_t Write(void* context, const void* buffer, size_t uiBufSize) { return -1; }
153
154 /// @brief Seek in a file
155 ///
156 /// @param[in] context The context of the file
157 /// @param[in] position The position to seek to
158 /// @param[in] whence Position in file 'position' is relative to (SEEK_CUR, SEEK_SET, SEEK_END)
159 /// @return Offset in file after seek
160 ///
161 virtual int64_t Seek(void* context, int64_t position, int whence) { return -1; }
162
163 /// @brief Truncate a file
164 ///
165 /// @param[in] context The context of the file
166 /// @param[in] size The size to truncate the file to
167 /// @return 0 on success, -1 on error
168 ///
169 virtual int Truncate(void* context, int64_t size) { return -1; }
170
171 /// @brief Get total size of a file
172 ///
173 /// @param[in] context The context of the file
174 /// @return Total file size
175 ///
176 virtual int64_t GetLength(void* context) { return 0; }
177
178 /// @brief Get current position in a file
179 ///
180 /// @param[in] context The context of the file
181 /// @return Current position
182 ///
183 virtual int64_t GetPosition(void* context) { return 0; }
184
185 /// @brief Get chunk size of a file
186 ///
187 /// @param[in] context The context of the file
188 /// @return Chunk size
189 ///
190 virtual int GetChunkSize(void* context) { return 1; }
191
192 /// @brief Perform an IO-control on the file
193 ///
194 /// @param[in] context The context of the file
195 /// @param[in] request The requested IO-control
196 /// @param[in] param Parameter attached to the IO-control
197 /// @return -1 on error, >= 0 on success
198 ///
199 virtual int IoControl(void* context, XFILE::EIoControl request, void* param) { return -1; }
200
201 /// @brief Close a file
202 ///
203 /// @param[in] context The context of the file
204 /// @return True on success, false on failure
205 ///
206 virtual bool Close(void* context) { return false; }
207
208 /// @brief Stat a file
209 ///
210 /// @param[in] url The URL of the file
211 /// @param[in] buffer The buffer to store results in
212 /// @return -1 on error, 0 otherwise
213 ///
214 virtual int Stat(const VFSURL& url, struct __stat64* buffer) { return 0; }
215
216 /// @brief Check for file existence
217 ///
218 /// @param[in] url The URL of the file
219 /// @return True if file exists, false otherwise
220 ///
221 virtual bool Exists(const VFSURL& url) { return false; }
222
223 /// @brief Clear out any idle connections
224 ///
225 virtual void ClearOutIdle() { }
226
227 /// @brief Disconnect all connections
228 ///
229 virtual void DisconnectAll() { }
230
231 /// @brief Delete a file
232 ///
233 /// @param[in] url The URL of the file
234 /// @return True if deletion was successful, false otherwise
235 ///
236 virtual bool Delete(const VFSURL& url) { return false; }
237
238 /// @brief Rename a file
239 ///
240 /// @param[in] url The URL of the source file
241 /// @param[in] url2 The URL of the destination file
242 /// @return True if deletion was successful, false otherwise
243 ///
244 virtual bool Rename(const VFSURL& url, const VFSURL& url2) { return false; }
245
246 /// @brief Check for directory existence
247 ///
248 /// @param[in] url The URL of the file
249 /// @return True if directory exists, false otherwise
250 ///
251 virtual bool DirectoryExists(const VFSURL& url) { return false; }
252
253 /// @brief Remove a directory
254 ///
255 /// @param[in] url The URL of the directory
256 /// @return True if removal was successful, false otherwise
257 ///
258 virtual bool RemoveDirectory(const VFSURL& url) { return false; }
259
260 /// @brief Create a directory
261 ///
262 /// @param[in] url The URL of the file
263 /// @return True if creation was successful, false otherwise
264 ///
265 virtual bool CreateDirectory(const VFSURL& url) { return false; }
266
267 /// @brief Callback functions on GetDirectory()
268 ///
269 /// This functions becomes available during call of GetDirectory() from
270 /// Kodi.
271 ///
272 /// If GetDirectory() returns false becomes the parts from here used on
273 /// next call of the function.
274 ///
275 /// **Example:**
276 /// ~~~~~~~~~~~~~{.cpp}
277 /// 874 ///
278 /// #include <kodi/addon-instance/VFS.h> 875 /// Becomes called if GetDirectory() returns false and GetDirectory()
876 /// becomes after entry called again.
279 /// 877 ///
280 /// ... 878 /// @param[in] heading The heading of the keyboard dialog
879 /// @param[out] input The resulting string. Returns string after
880 /// second call!
881 /// @param[in] hiddenInput To show input only as "*" on dialog
882 /// @return True if input was received, false otherwise
281 /// 883 ///
282 /// bool CMyFile::GetDirectory(const VFSURL& url, std::vector<kodi::vfs::CDirEntry>& items, CVFSCallbacks callbacks) 884 bool GetKeyboardInput(const std::string& heading, std::string& input, bool hiddenInput = false)
283 /// {
284 /// std::string neededString;
285 /// callbacks.GetKeyboardInput("Test", neededString, true);
286 /// if (neededString.empty())
287 /// return false;
288 ///
289 /// /* Do the work */
290 /// ...
291 /// return true;
292 /// }
293 /// ~~~~~~~~~~~~~
294 ///
295 //@{
296 class CVFSCallbacks
297 { 885 {
298 public: 886 char* cInput = nullptr;
299 /// @brief Require keyboard input 887 bool ret = m_cb->get_keyboard_input(m_cb->ctx, heading.c_str(), &cInput, hiddenInput);
300 /// 888 if (cInput)
301 /// Becomes called if GetDirectory() returns false and GetDirectory()
302 /// becomes after entry called again.
303 ///
304 /// @param[in] heading The heading of the keyboard dialog
305 /// @param[out] input The resulting string. Returns string after
306 /// second call!
307 /// @param[in] hiddenInput To show input only as "*" on dialog
308 /// @return True if input was received, false otherwise
309 ///
310 bool GetKeyboardInput(const std::string& heading, std::string& input, bool hiddenInput = false)
311 {
312 char* cInput = nullptr;
313 bool ret = m_cb->get_keyboard_input(m_cb->ctx, heading.c_str(), &cInput, hiddenInput);
314 if (cInput)
315 {
316 input = cInput;
317 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cInput);
318 }
319 return ret;
320 }
321
322 /// @brief Display an error dialog
323 ///
324 /// @param[in] heading The heading of the error dialog
325 /// @param[in] line1 The first line of the error dialog
326 /// @param[in] line2 [opt] The second line of the error dialog
327 /// @param[in] line3 [opt] The third line of the error dialog
328 ///
329 void SetErrorDialog(const std::string& heading, const std::string& line1, const std::string& line2 = "", const std::string& line3 = "")
330 {
331 m_cb->set_error_dialog(m_cb->ctx, heading.c_str(), line1.c_str(), line2.c_str(), line3.c_str());
332 }
333
334 /// @brief Prompt the user for authentication of a URL
335 ///
336 /// @param[in] url The URL
337 void RequireAuthentication(const std::string& url)
338 { 889 {
339 m_cb->require_authentication(m_cb->ctx, url.c_str()); 890 input = cInput;
891 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(
892 ::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cInput);
340 } 893 }
894 return ret;
895 }
341 896
342 explicit CVFSCallbacks(const VFSGetDirectoryCallbacks* cb) : m_cb(cb) { } 897 /// @ingroup cpp_kodi_addon_vfs_general_cb_GetDirectory
343 898 /// @brief Display an error dialog
344 private:
345 const VFSGetDirectoryCallbacks* m_cb;
346 };
347 //@}
348
349 /// @brief List a directory
350 ///
351 /// @param[in] url The URL of the directory
352 /// @param[out] entries The entries in the directory
353 /// @param[in] callbacks A callback structure
354 /// @return Context for the directory listing
355 ///
356 virtual bool GetDirectory(const VFSURL& url,
357 std::vector<kodi::vfs::CDirEntry>& entries,
358 CVFSCallbacks callbacks) { return false; }
359
360 /// @brief Check if file should be presented as a directory (multiple streams)
361 /// 899 ///
362 /// @param[in] url The URL of the file 900 /// @param[in] heading The heading of the error dialog
363 /// @param[out] entries The entries in the directory 901 /// @param[in] line1 The first line of the error dialog
364 /// @param[out] rootPath Path to root directory if multiple entries 902 /// @param[in] line2 [opt] The second line of the error dialog
365 /// @return Context for the directory listing 903 /// @param[in] line3 [opt] The third line of the error dialog
366 /// 904 ///
367 virtual bool ContainsFiles(const VFSURL& url, 905 void SetErrorDialog(const std::string& heading,
368 std::vector<kodi::vfs::CDirEntry>& entries, 906 const std::string& line1,
369 std::string& rootPath) { return false; } 907 const std::string& line2 = "",
370 908 const std::string& line3 = "")
371 private:
372 void SetAddonStruct(KODI_HANDLE instance)
373 {
374 if (instance == nullptr)
375 throw std::logic_error("kodi::addon::CInstanceVFS: Creation with empty addon structure not allowed, table must be given from Kodi!");
376
377 m_instanceData = static_cast<AddonInstance_VFSEntry*>(instance);
378 m_instanceData->toAddon.addonInstance = this;
379 m_instanceData->toAddon.open = ADDON_Open;
380 m_instanceData->toAddon.open_for_write = ADDON_OpenForWrite;
381 m_instanceData->toAddon.read = ADDON_Read;
382 m_instanceData->toAddon.write = ADDON_Write;
383 m_instanceData->toAddon.seek = ADDON_Seek;
384 m_instanceData->toAddon.truncate = ADDON_Truncate;
385 m_instanceData->toAddon.get_length = ADDON_GetLength;
386 m_instanceData->toAddon.get_position = ADDON_GetPosition;
387 m_instanceData->toAddon.get_chunk_size = ADDON_GetChunkSize;
388 m_instanceData->toAddon.io_control = ADDON_IoControl;
389 m_instanceData->toAddon.stat = ADDON_Stat;
390 m_instanceData->toAddon.close = ADDON_Close;
391 m_instanceData->toAddon.exists = ADDON_Exists;
392 m_instanceData->toAddon.clear_out_idle = ADDON_ClearOutIdle;
393 m_instanceData->toAddon.disconnect_all = ADDON_DisconnectAll;
394 m_instanceData->toAddon.delete_it = ADDON_Delete;
395 m_instanceData->toAddon.rename = ADDON_Rename;
396 m_instanceData->toAddon.directory_exists = ADDON_DirectoryExists;
397 m_instanceData->toAddon.remove_directory = ADDON_RemoveDirectory;
398 m_instanceData->toAddon.create_directory = ADDON_CreateDirectory;
399 m_instanceData->toAddon.get_directory = ADDON_GetDirectory;
400 m_instanceData->toAddon.free_directory = ADDON_FreeDirectory;
401 m_instanceData->toAddon.contains_files = ADDON_ContainsFiles;
402 }
403
404 inline static void* ADDON_Open(const AddonInstance_VFSEntry* instance, const VFSURL* url)
405 { 909 {
406 return instance->toAddon.addonInstance->Open(*url); 910 m_cb->set_error_dialog(m_cb->ctx, heading.c_str(), line1.c_str(), line2.c_str(),
911 line3.c_str());
407 } 912 }
408 913
409 inline static void* ADDON_OpenForWrite(const AddonInstance_VFSEntry* instance, const VFSURL* url, bool overWrite) 914 /// @ingroup cpp_kodi_addon_vfs_general_cb_GetDirectory
915 /// @brief Prompt the user for authentication of a URL
916 ///
917 /// @param[in] url The URL
918 void RequireAuthentication(const std::string& url)
410 { 919 {
411 return instance->toAddon.addonInstance->OpenForWrite(*url, overWrite); 920 m_cb->require_authentication(m_cb->ctx, url.c_str());
412 } 921 }
413 922
414 inline static ssize_t ADDON_Read(const AddonInstance_VFSEntry* instance, void* context, void* buffer, size_t uiBufSize) 923 explicit CVFSCallbacks(const VFSGetDirectoryCallbacks* cb) : m_cb(cb) {}
415 {
416 return instance->toAddon.addonInstance->Read(context, buffer, uiBufSize);
417 }
418 924
419 inline static ssize_t ADDON_Write(const AddonInstance_VFSEntry* instance, void* context, const void* buffer, size_t uiBufSize) 925 private:
420 { 926 const VFSGetDirectoryCallbacks* m_cb;
421 return instance->toAddon.addonInstance->Write(context, buffer, uiBufSize); 927 };
422 } 928 //--------------------------------------------------------------------------
929
930 //==========================================================================
931 ///
932 /// @ingroup cpp_kodi_addon_vfs_general
933 /// @brief List a directory
934 ///
935 /// @param[in] url The URL of the directory
936 /// @param[out] entries The entries in the directory, see
937 /// @ref cpp_kodi_vfs_CDirEntry "kodi::vfs::CDirEntry"
938 /// about his content
939 /// @param[in] callbacks A callback structure
940 /// @return Context for the directory listing
941 ///
942 ///
943 /// --------------------------------------------------------------------------
944 ///
945 /// ### Callbacks:
946 /// @copydetails cpp_kodi_addon_vfs_general_cb_GetDirectory
947 ///
948 /// **Available callback functions**
949 /// | Function: | Description
950 /// |--|--
951 /// | CVFSCallbacks::GetKeyboardInput | @copybrief CVFSCallbacks::GetKeyboardInput @copydetails CVFSCallbacks::GetKeyboardInput
952 /// | CVFSCallbacks::SetErrorDialog | @copybrief CVFSCallbacks::SetErrorDialog @copydetails CVFSCallbacks::SetErrorDialog
953 /// | CVFSCallbacks::RequireAuthentication | @copybrief CVFSCallbacks::RequireAuthentication @copydetails CVFSCallbacks::RequireAuthentication
954 ///
955 virtual bool GetDirectory(const VFSURL& url,
956 std::vector<kodi::vfs::CDirEntry>& entries,
957 CVFSCallbacks callbacks)
958 {
959 return false;
960 }
961 //--------------------------------------------------------------------------
962
963 //==========================================================================
964 ///
965 /// @ingroup cpp_kodi_addon_vfs_general
966 /// @brief Check if file should be presented as a directory (multiple streams)
967 ///
968 /// @param[in] url The URL of the file
969 /// @param[out] entries The entries in the directory, see
970 /// @ref cpp_kodi_vfs_CDirEntry "kodi::vfs::CDirEntry"
971 /// about his content
972 /// @param[out] rootPath Path to root directory if multiple entries
973 /// @return Context for the directory listing
974 ///
975 virtual bool ContainsFiles(const VFSURL& url,
976 std::vector<kodi::vfs::CDirEntry>& entries,
977 std::string& rootPath)
978 {
979 return false;
980 }
981 //--------------------------------------------------------------------------
982 //@}
423 983
424 inline static int64_t ADDON_Seek(const AddonInstance_VFSEntry* instance, void* context, int64_t position, int whence) 984private:
425 { 985 void SetAddonStruct(KODI_HANDLE instance)
426 return instance->toAddon.addonInstance->Seek(context, position, whence); 986 {
427 } 987 if (instance == nullptr)
988 throw std::logic_error("kodi::addon::CInstanceVFS: Creation with empty addon structure not "
989 "allowed, table must be given from Kodi!");
990
991 m_instanceData = static_cast<AddonInstance_VFSEntry*>(instance);
992 m_instanceData->toAddon->addonInstance = this;
993 m_instanceData->toAddon->open = ADDON_Open;
994 m_instanceData->toAddon->open_for_write = ADDON_OpenForWrite;
995 m_instanceData->toAddon->read = ADDON_Read;
996 m_instanceData->toAddon->write = ADDON_Write;
997 m_instanceData->toAddon->seek = ADDON_Seek;
998 m_instanceData->toAddon->truncate = ADDON_Truncate;
999 m_instanceData->toAddon->get_length = ADDON_GetLength;
1000 m_instanceData->toAddon->get_position = ADDON_GetPosition;
1001 m_instanceData->toAddon->get_chunk_size = ADDON_GetChunkSize;
1002 m_instanceData->toAddon->io_control = ADDON_IoControl;
1003 m_instanceData->toAddon->stat = ADDON_Stat;
1004 m_instanceData->toAddon->close = ADDON_Close;
1005 m_instanceData->toAddon->exists = ADDON_Exists;
1006 m_instanceData->toAddon->clear_out_idle = ADDON_ClearOutIdle;
1007 m_instanceData->toAddon->disconnect_all = ADDON_DisconnectAll;
1008 m_instanceData->toAddon->delete_it = ADDON_Delete;
1009 m_instanceData->toAddon->rename = ADDON_Rename;
1010 m_instanceData->toAddon->directory_exists = ADDON_DirectoryExists;
1011 m_instanceData->toAddon->remove_directory = ADDON_RemoveDirectory;
1012 m_instanceData->toAddon->create_directory = ADDON_CreateDirectory;
1013 m_instanceData->toAddon->get_directory = ADDON_GetDirectory;
1014 m_instanceData->toAddon->free_directory = ADDON_FreeDirectory;
1015 m_instanceData->toAddon->contains_files = ADDON_ContainsFiles;
1016 }
1017
1018 inline static void* ADDON_Open(const AddonInstance_VFSEntry* instance, const VFSURL* url)
1019 {
1020 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Open(*url);
1021 }
428 1022
429 inline static int ADDON_Truncate(const AddonInstance_VFSEntry* instance, void* context, int64_t size) 1023 inline static void* ADDON_OpenForWrite(const AddonInstance_VFSEntry* instance,
430 { 1024 const VFSURL* url,
431 return instance->toAddon.addonInstance->Truncate(context, size); 1025 bool overWrite)
432 } 1026 {
1027 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1028 ->OpenForWrite(*url, overWrite);
1029 }
1030
1031 inline static ssize_t ADDON_Read(const AddonInstance_VFSEntry* instance,
1032 void* context,
1033 void* buffer,
1034 size_t uiBufSize)
1035 {
1036 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1037 ->Read(context, buffer, uiBufSize);
1038 }
1039
1040 inline static ssize_t ADDON_Write(const AddonInstance_VFSEntry* instance,
1041 void* context,
1042 const void* buffer,
1043 size_t uiBufSize)
1044 {
1045 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1046 ->Write(context, buffer, uiBufSize);
1047 }
1048
1049 inline static int64_t ADDON_Seek(const AddonInstance_VFSEntry* instance,
1050 void* context,
1051 int64_t position,
1052 int whence)
1053 {
1054 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1055 ->Seek(context, position, whence);
1056 }
433 1057
434 inline static int64_t ADDON_GetLength(const AddonInstance_VFSEntry* instance, void* context) 1058 inline static int ADDON_Truncate(const AddonInstance_VFSEntry* instance,
435 { 1059 void* context,
436 return instance->toAddon.addonInstance->GetLength(context); 1060 int64_t size)
437 } 1061 {
1062 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Truncate(context, size);
1063 }
438 1064
439 inline static int64_t ADDON_GetPosition(const AddonInstance_VFSEntry* instance, void* context) 1065 inline static int64_t ADDON_GetLength(const AddonInstance_VFSEntry* instance, void* context)
440 { 1066 {
441 return instance->toAddon.addonInstance->GetPosition(context); 1067 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetLength(context);
442 } 1068 }
443 1069
444 inline static int ADDON_GetChunkSize(const AddonInstance_VFSEntry* instance, void* context) 1070 inline static int64_t ADDON_GetPosition(const AddonInstance_VFSEntry* instance, void* context)
445 { 1071 {
446 return instance->toAddon.addonInstance->GetChunkSize(context); 1072 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetPosition(context);
447 } 1073 }
448 1074
449 inline static int ADDON_IoControl(const AddonInstance_VFSEntry* instance, void* context, XFILE::EIoControl request, void* param) 1075 inline static int ADDON_GetChunkSize(const AddonInstance_VFSEntry* instance, void* context)
450 { 1076 {
451 return instance->toAddon.addonInstance->IoControl(context, request, param); 1077 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetChunkSize(context);
452 } 1078 }
453 1079
454 inline static int ADDON_Stat(const AddonInstance_VFSEntry* instance, const VFSURL* url, struct __stat64* buffer) 1080 inline static int ADDON_IoControl(const AddonInstance_VFSEntry* instance,
455 { 1081 void* context,
456 return instance->toAddon.addonInstance->Stat(*url, buffer); 1082 enum VFS_IOCTRL request,
457 } 1083 void* param)
1084 {
1085 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1086 ->IoControl(context, request, param);
1087 }
458 1088
459 inline static bool ADDON_Close(const AddonInstance_VFSEntry* instance, void* context) 1089 inline static int ADDON_Stat(const AddonInstance_VFSEntry* instance,
460 { 1090 const VFSURL* url,
461 return instance->toAddon.addonInstance->Close(context); 1091 struct __stat64* buffer)
462 } 1092 {
1093 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Stat(*url, buffer);
1094 }
463 1095
464 inline static bool ADDON_Exists(const AddonInstance_VFSEntry* instance, const VFSURL* url) 1096 inline static bool ADDON_Close(const AddonInstance_VFSEntry* instance, void* context)
465 { 1097 {
466 return instance->toAddon.addonInstance->Exists(*url); 1098 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Close(context);
467 } 1099 }
468 1100
469 inline static void ADDON_ClearOutIdle(const AddonInstance_VFSEntry* instance) 1101 inline static bool ADDON_Exists(const AddonInstance_VFSEntry* instance, const VFSURL* url)
470 { 1102 {
471 return instance->toAddon.addonInstance->ClearOutIdle(); 1103 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Exists(*url);
472 } 1104 }
473 1105
474 inline static void ADDON_DisconnectAll(const AddonInstance_VFSEntry* instance) 1106 inline static void ADDON_ClearOutIdle(const AddonInstance_VFSEntry* instance)
475 { 1107 {
476 return instance->toAddon.addonInstance->DisconnectAll(); 1108 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->ClearOutIdle();
477 } 1109 }
478 1110
479 inline static bool ADDON_Delete(const AddonInstance_VFSEntry* instance, const VFSURL* url) 1111 inline static void ADDON_DisconnectAll(const AddonInstance_VFSEntry* instance)
480 { 1112 {
481 return instance->toAddon.addonInstance->Delete(*url); 1113 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->DisconnectAll();
482 } 1114 }
483 1115
484 inline static bool ADDON_Rename(const AddonInstance_VFSEntry* instance, const VFSURL* url, const VFSURL* url2) 1116 inline static bool ADDON_Delete(const AddonInstance_VFSEntry* instance, const VFSURL* url)
485 { 1117 {
486 return instance->toAddon.addonInstance->Rename(*url, *url2); 1118 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Delete(*url);
487 } 1119 }
488 1120
489 inline static bool ADDON_DirectoryExists(const AddonInstance_VFSEntry* instance, const VFSURL* url) 1121 inline static bool ADDON_Rename(const AddonInstance_VFSEntry* instance,
490 { 1122 const VFSURL* url,
491 return instance->toAddon.addonInstance->DirectoryExists(*url); 1123 const VFSURL* url2)
492 } 1124 {
1125 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Rename(*url, *url2);
1126 }
493 1127
494 inline static bool ADDON_RemoveDirectory(const AddonInstance_VFSEntry* instance, const VFSURL* url) 1128 inline static bool ADDON_DirectoryExists(const AddonInstance_VFSEntry* instance,
495 { 1129 const VFSURL* url)
496 return instance->toAddon.addonInstance->RemoveDirectory(*url); 1130 {
497 } 1131 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->DirectoryExists(*url);
1132 }
498 1133
499 inline static bool ADDON_CreateDirectory(const AddonInstance_VFSEntry* instance, const VFSURL* url) 1134 inline static bool ADDON_RemoveDirectory(const AddonInstance_VFSEntry* instance,
500 { 1135 const VFSURL* url)
501 return instance->toAddon.addonInstance->CreateDirectory(*url); 1136 {
502 } 1137 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->RemoveDirectory(*url);
1138 }
503 1139
504 inline static bool ADDON_GetDirectory(const AddonInstance_VFSEntry* instance, 1140 inline static bool ADDON_CreateDirectory(const AddonInstance_VFSEntry* instance,
505 const VFSURL* url, 1141 const VFSURL* url)
506 VFSDirEntry** retEntries, 1142 {
507 int* num_entries, 1143 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->CreateDirectory(*url);
508 VFSGetDirectoryCallbacks* callbacks) 1144 }
1145
1146 inline static bool ADDON_GetDirectory(const AddonInstance_VFSEntry* instance,
1147 const VFSURL* url,
1148 VFSDirEntry** retEntries,
1149 int* num_entries,
1150 VFSGetDirectoryCallbacks* callbacks)
1151 {
1152 std::vector<kodi::vfs::CDirEntry> addonEntries;
1153 bool ret = static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1154 ->GetDirectory(*url, addonEntries, CVFSCallbacks(callbacks));
1155 if (ret)
509 { 1156 {
510 std::vector<kodi::vfs::CDirEntry> addonEntries; 1157 VFSDirEntry* entries =
511 bool ret = instance->toAddon.addonInstance->GetDirectory(*url, addonEntries, CVFSCallbacks(callbacks)); 1158 static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size()));
512 if (ret) 1159 for (unsigned int i = 0; i < addonEntries.size(); ++i)
513 { 1160 {
514 VFSDirEntry* entries = static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size())); 1161 entries[i].label = strdup(addonEntries[i].Label().c_str());
515 for (unsigned int i = 0; i < addonEntries.size(); ++i) 1162 entries[i].title = strdup(addonEntries[i].Title().c_str());
1163 entries[i].path = strdup(addonEntries[i].Path().c_str());
1164 entries[i].folder = addonEntries[i].IsFolder();
1165 entries[i].size = addonEntries[i].Size();
1166 entries[i].date_time = addonEntries[i].DateTime();
1167
1168 entries[i].num_props = 0;
1169 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
1170 if (!props.empty())
516 { 1171 {
517 entries[i].label = strdup(addonEntries[i].Label().c_str()); 1172 entries[i].properties =
518 entries[i].title = strdup(addonEntries[i].Title().c_str()); 1173 static_cast<VFSProperty*>(malloc(sizeof(VFSProperty) * props.size()));
519 entries[i].path = strdup(addonEntries[i].Path().c_str()); 1174 for (const auto& prop : props)
520 entries[i].folder = addonEntries[i].IsFolder();
521 entries[i].size = addonEntries[i].Size();
522
523 entries[i].num_props = 0;
524 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
525 if (!props.empty())
526 { 1175 {
527 entries[i].properties = static_cast<VFSProperty*>(malloc(sizeof(VFSProperty)*props.size())); 1176 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
528 for (const auto& prop : props) 1177 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
529 { 1178 ++entries[i].num_props;
530 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
531 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
532 ++entries[i].num_props;
533 }
534 } 1179 }
535 else
536 entries[i].properties = nullptr;
537 } 1180 }
538 *retEntries = entries; 1181 else
539 *num_entries = static_cast<int>(addonEntries.size()); 1182 entries[i].properties = nullptr;
540 } 1183 }
541 return ret; 1184 *retEntries = entries;
1185 *num_entries = static_cast<int>(addonEntries.size());
542 } 1186 }
1187 return ret;
1188 }
543 1189
544 inline static void ADDON_FreeDirectory(const AddonInstance_VFSEntry* instance, VFSDirEntry* entries, int num_entries) 1190 inline static void ADDON_FreeDirectory(const AddonInstance_VFSEntry* instance,
1191 VFSDirEntry* entries,
1192 int num_entries)
1193 {
1194 for (int i = 0; i < num_entries; ++i)
545 { 1195 {
546 for (int i = 0; i < num_entries; ++i) 1196 if (entries[i].properties)
547 { 1197 {
548 if (entries[i].properties) 1198 for (unsigned int j = 0; j < entries[i].num_props; ++j)
549 { 1199 {
550 for (unsigned int j = 0; j < entries[i].num_props; ++j) 1200 free(entries[i].properties[j].name);
551 { 1201 free(entries[i].properties[j].val);
552 free(entries[i].properties[j].name);
553 free(entries[i].properties[j].val);
554 }
555 free(entries[i].properties);
556 } 1202 }
557 free(entries[i].label); 1203 free(entries[i].properties);
558 free(entries[i].title);
559 free(entries[i].path);
560 } 1204 }
561 free(entries); 1205 free(entries[i].label);
1206 free(entries[i].title);
1207 free(entries[i].path);
562 } 1208 }
563 1209 free(entries);
564 inline static bool ADDON_ContainsFiles(const AddonInstance_VFSEntry* instance, 1210 }
565 const VFSURL* url, 1211
566 VFSDirEntry** retEntries, 1212 inline static bool ADDON_ContainsFiles(const AddonInstance_VFSEntry* instance,
567 int* num_entries, 1213 const VFSURL* url,
568 char* rootpath) 1214 VFSDirEntry** retEntries,
1215 int* num_entries,
1216 char* rootpath)
1217 {
1218 std::string cppRootPath;
1219 std::vector<kodi::vfs::CDirEntry> addonEntries;
1220 bool ret = static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1221 ->ContainsFiles(*url, addonEntries, cppRootPath);
1222 if (ret)
569 { 1223 {
570 std::string cppRootPath; 1224 strncpy(rootpath, cppRootPath.c_str(), ADDON_STANDARD_STRING_LENGTH);
571 std::vector<kodi::vfs::CDirEntry> addonEntries;
572 bool ret = instance->toAddon.addonInstance->ContainsFiles(*url, addonEntries, cppRootPath);
573 if (ret)
574 {
575 strncpy(rootpath, cppRootPath.c_str(), ADDON_STANDARD_STRING_LENGTH);
576 1225
577 VFSDirEntry* entries = static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size())); 1226 VFSDirEntry* entries =
578 for (size_t i = 0; i < addonEntries.size(); ++i) 1227 static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size()));
1228 for (size_t i = 0; i < addonEntries.size(); ++i)
1229 {
1230 entries[i].label = strdup(addonEntries[i].Label().c_str());
1231 entries[i].title = strdup(addonEntries[i].Title().c_str());
1232 entries[i].path = strdup(addonEntries[i].Path().c_str());
1233 entries[i].folder = addonEntries[i].IsFolder();
1234 entries[i].size = addonEntries[i].Size();
1235 entries[i].date_time = addonEntries[i].DateTime();
1236
1237 entries[i].num_props = 0;
1238 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
1239 if (!props.empty())
579 { 1240 {
580 entries[i].label = strdup(addonEntries[i].Label().c_str()); 1241 entries[i].properties =
581 entries[i].title = strdup(addonEntries[i].Title().c_str()); 1242 static_cast<VFSProperty*>(malloc(sizeof(VFSProperty) * props.size()));
582 entries[i].path = strdup(addonEntries[i].Path().c_str()); 1243 for (const auto& prop : props)
583 entries[i].folder = addonEntries[i].IsFolder();
584 entries[i].size = addonEntries[i].Size();
585
586 entries[i].num_props = 0;
587 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
588 if (!props.empty())
589 { 1244 {
590 entries[i].properties = static_cast<VFSProperty*>(malloc(sizeof(VFSProperty)*props.size())); 1245 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
591 for (const auto& prop : props) 1246 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
592 { 1247 ++entries[i].num_props;
593 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
594 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
595 ++entries[i].num_props;
596 }
597 } 1248 }
598 else
599 entries[i].properties = nullptr;
600 } 1249 }
601 *retEntries = entries; 1250 else
602 *num_entries = static_cast<int>(addonEntries.size()); 1251 entries[i].properties = nullptr;
603 } 1252 }
604 return ret; 1253 *retEntries = entries;
1254 *num_entries = static_cast<int>(addonEntries.size());
605 } 1255 }
1256 return ret;
1257 }
606 1258
607 AddonInstance_VFSEntry* m_instanceData; 1259 AddonInstance_VFSEntry* m_instanceData;
608 }; 1260};
609 1261
610} /* namespace addon */ 1262} /* namespace addon */
611} /* namespace kodi */ 1263} /* namespace kodi */
1264
1265#endif /* __cplusplus */