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.h1265
1 files changed, 0 insertions, 1265 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
deleted file mode 100644
index efd5de2..0000000
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
+++ /dev/null
@@ -1,1265 +0,0 @@
1/*
2 * Copyright (C) 2015-2018 Team Kodi
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSES/README.md for more information.
6 */
7
8#pragma once
9
10#include "../AddonBase.h"
11#include "../Filesystem.h"
12
13#if !defined(_WIN32)
14#include <sys/stat.h>
15#if !defined(__stat64)
16#if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
17#define __stat64 stat
18#else
19#define __stat64 stat64
20#endif
21#endif
22#endif
23
24#ifdef __cplusplus
25extern "C"
26{
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 ///
36 struct VFSURL
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>
43 const char* url;
44
45 /// @brief The associated domain name, which is optional and not available
46 /// in all cases.
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`).
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`).
56 const char* filename;
57
58 /// @brief [Networking port](https://en.wikipedia.org/wiki/Port_(computer_networking))
59 /// to use for protocol.
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.
76 const char* options;
77
78 /// @brief Desired username.
79 const char* username;
80
81 /// @brief Desired 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>.
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.
95 const char* sharename;
96
97 /// @brief Protocol name used on this stream, e.g. <b>`sftp`</b>.
98 const char* protocol;
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 //----------------------------------------------------------------------------
169
170 typedef struct VFSGetDirectoryCallbacks /* internal */
171 {
172 bool (__cdecl* get_keyboard_input)(void* ctx, const char* heading, char** input, bool hidden_input);
173 void (__cdecl* set_error_dialog)(void* ctx, const char* heading, const char* line1, const char* line2, const char* line3);
174 void (__cdecl* require_authentication)(void* ctx, const char* url);
175 void* ctx;
176 } VFSGetDirectoryCallbacks;
177
178 typedef struct AddonProps_VFSEntry /* internal */
179 {
180 int dummy;
181 } AddonProps_VFSEntry;
182
183 typedef struct AddonToKodiFuncTable_VFSEntry /* internal */
184 {
185 KODI_HANDLE kodiInstance;
186 } AddonToKodiFuncTable_VFSEntry;
187
188 struct AddonInstance_VFSEntry;
189 typedef struct KodiToAddonFuncTable_VFSEntry /* internal */
190 {
191 KODI_HANDLE addonInstance;
192
193 void*(__cdecl* open)(const struct AddonInstance_VFSEntry* instance, const struct VFSURL* url);
194 void*(__cdecl* open_for_write)(const struct AddonInstance_VFSEntry* instance,
195 const struct VFSURL* url,
196 bool overwrite);
197 ssize_t(__cdecl* read)(const struct AddonInstance_VFSEntry* instance,
198 void* context,
199 void* buffer,
200 size_t buf_size);
201 ssize_t(__cdecl* write)(const struct AddonInstance_VFSEntry* instance,
202 void* context,
203 const void* buffer,
204 size_t buf_size);
205 int64_t(__cdecl* seek)(const struct AddonInstance_VFSEntry* instance,
206 void* context,
207 int64_t position,
208 int whence);
209 int(__cdecl* truncate)(const struct AddonInstance_VFSEntry* instance,
210 void* context,
211 int64_t size);
212 int64_t(__cdecl* get_length)(const struct AddonInstance_VFSEntry* instance, void* context);
213 int64_t(__cdecl* get_position)(const struct AddonInstance_VFSEntry* instance, void* context);
214 int(__cdecl* get_chunk_size)(const struct AddonInstance_VFSEntry* instance, void* context);
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,
245 int* num_entries,
246 char* rootpath);
247 void(__cdecl* free_directory)(const struct AddonInstance_VFSEntry* instance,
248 struct VFSDirEntry* entries,
249 int num_entries);
250 } KodiToAddonFuncTable_VFSEntry;
251
252 typedef struct AddonInstance_VFSEntry /* internal */
253 {
254 AddonProps_VFSEntry* props;
255 AddonToKodiFuncTable_VFSEntry* toKodi;
256 KodiToAddonFuncTable_VFSEntry* toAddon;
257 } AddonInstance_VFSEntry;
258
259#ifdef __cplusplus
260} /* extern "C" */
261
262namespace kodi
263{
264namespace addon
265{
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
870 {
871 public:
872 /// @ingroup cpp_kodi_addon_vfs_general_cb_GetDirectory
873 /// @brief Require keyboard input
874 ///
875 /// Becomes called if GetDirectory() returns false and GetDirectory()
876 /// becomes after entry called again.
877 ///
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
883 ///
884 bool GetKeyboardInput(const std::string& heading, std::string& input, bool hiddenInput = false)
885 {
886 char* cInput = nullptr;
887 bool ret = m_cb->get_keyboard_input(m_cb->ctx, heading.c_str(), &cInput, hiddenInput);
888 if (cInput)
889 {
890 input = cInput;
891 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(
892 ::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cInput);
893 }
894 return ret;
895 }
896
897 /// @ingroup cpp_kodi_addon_vfs_general_cb_GetDirectory
898 /// @brief Display an error dialog
899 ///
900 /// @param[in] heading The heading of the error dialog
901 /// @param[in] line1 The first line of the error dialog
902 /// @param[in] line2 [opt] The second line of the error dialog
903 /// @param[in] line3 [opt] The third line of the error dialog
904 ///
905 void SetErrorDialog(const std::string& heading,
906 const std::string& line1,
907 const std::string& line2 = "",
908 const std::string& line3 = "")
909 {
910 m_cb->set_error_dialog(m_cb->ctx, heading.c_str(), line1.c_str(), line2.c_str(),
911 line3.c_str());
912 }
913
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)
919 {
920 m_cb->require_authentication(m_cb->ctx, url.c_str());
921 }
922
923 explicit CVFSCallbacks(const VFSGetDirectoryCallbacks* cb) : m_cb(cb) {}
924
925 private:
926 const VFSGetDirectoryCallbacks* m_cb;
927 };
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 //@}
983
984private:
985 void SetAddonStruct(KODI_HANDLE instance)
986 {
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 }
1022
1023 inline static void* ADDON_OpenForWrite(const AddonInstance_VFSEntry* instance,
1024 const VFSURL* url,
1025 bool overWrite)
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 }
1057
1058 inline static int ADDON_Truncate(const AddonInstance_VFSEntry* instance,
1059 void* context,
1060 int64_t size)
1061 {
1062 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Truncate(context, size);
1063 }
1064
1065 inline static int64_t ADDON_GetLength(const AddonInstance_VFSEntry* instance, void* context)
1066 {
1067 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetLength(context);
1068 }
1069
1070 inline static int64_t ADDON_GetPosition(const AddonInstance_VFSEntry* instance, void* context)
1071 {
1072 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetPosition(context);
1073 }
1074
1075 inline static int ADDON_GetChunkSize(const AddonInstance_VFSEntry* instance, void* context)
1076 {
1077 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->GetChunkSize(context);
1078 }
1079
1080 inline static int ADDON_IoControl(const AddonInstance_VFSEntry* instance,
1081 void* context,
1082 enum VFS_IOCTRL request,
1083 void* param)
1084 {
1085 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)
1086 ->IoControl(context, request, param);
1087 }
1088
1089 inline static int ADDON_Stat(const AddonInstance_VFSEntry* instance,
1090 const VFSURL* url,
1091 struct __stat64* buffer)
1092 {
1093 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Stat(*url, buffer);
1094 }
1095
1096 inline static bool ADDON_Close(const AddonInstance_VFSEntry* instance, void* context)
1097 {
1098 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Close(context);
1099 }
1100
1101 inline static bool ADDON_Exists(const AddonInstance_VFSEntry* instance, const VFSURL* url)
1102 {
1103 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Exists(*url);
1104 }
1105
1106 inline static void ADDON_ClearOutIdle(const AddonInstance_VFSEntry* instance)
1107 {
1108 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->ClearOutIdle();
1109 }
1110
1111 inline static void ADDON_DisconnectAll(const AddonInstance_VFSEntry* instance)
1112 {
1113 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->DisconnectAll();
1114 }
1115
1116 inline static bool ADDON_Delete(const AddonInstance_VFSEntry* instance, const VFSURL* url)
1117 {
1118 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Delete(*url);
1119 }
1120
1121 inline static bool ADDON_Rename(const AddonInstance_VFSEntry* instance,
1122 const VFSURL* url,
1123 const VFSURL* url2)
1124 {
1125 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->Rename(*url, *url2);
1126 }
1127
1128 inline static bool ADDON_DirectoryExists(const AddonInstance_VFSEntry* instance,
1129 const VFSURL* url)
1130 {
1131 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->DirectoryExists(*url);
1132 }
1133
1134 inline static bool ADDON_RemoveDirectory(const AddonInstance_VFSEntry* instance,
1135 const VFSURL* url)
1136 {
1137 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->RemoveDirectory(*url);
1138 }
1139
1140 inline static bool ADDON_CreateDirectory(const AddonInstance_VFSEntry* instance,
1141 const VFSURL* url)
1142 {
1143 return static_cast<CInstanceVFS*>(instance->toAddon->addonInstance)->CreateDirectory(*url);
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)
1156 {
1157 VFSDirEntry* entries =
1158 static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size()));
1159 for (unsigned int i = 0; i < addonEntries.size(); ++i)
1160 {
1161 entries[i].label = strdup(addonEntries[i].Label().c_str());
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())
1171 {
1172 entries[i].properties =
1173 static_cast<VFSProperty*>(malloc(sizeof(VFSProperty) * props.size()));
1174 for (const auto& prop : props)
1175 {
1176 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
1177 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
1178 ++entries[i].num_props;
1179 }
1180 }
1181 else
1182 entries[i].properties = nullptr;
1183 }
1184 *retEntries = entries;
1185 *num_entries = static_cast<int>(addonEntries.size());
1186 }
1187 return ret;
1188 }
1189
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)
1195 {
1196 if (entries[i].properties)
1197 {
1198 for (unsigned int j = 0; j < entries[i].num_props; ++j)
1199 {
1200 free(entries[i].properties[j].name);
1201 free(entries[i].properties[j].val);
1202 }
1203 free(entries[i].properties);
1204 }
1205 free(entries[i].label);
1206 free(entries[i].title);
1207 free(entries[i].path);
1208 }
1209 free(entries);
1210 }
1211
1212 inline static bool ADDON_ContainsFiles(const AddonInstance_VFSEntry* instance,
1213 const VFSURL* url,
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)
1223 {
1224 strncpy(rootpath, cppRootPath.c_str(), ADDON_STANDARD_STRING_LENGTH);
1225
1226 VFSDirEntry* entries =
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())
1240 {
1241 entries[i].properties =
1242 static_cast<VFSProperty*>(malloc(sizeof(VFSProperty) * props.size()));
1243 for (const auto& prop : props)
1244 {
1245 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
1246 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
1247 ++entries[i].num_props;
1248 }
1249 }
1250 else
1251 entries[i].properties = nullptr;
1252 }
1253 *retEntries = entries;
1254 *num_entries = static_cast<int>(addonEntries.size());
1255 }
1256 return ret;
1257 }
1258
1259 AddonInstance_VFSEntry* m_instanceData;
1260};
1261
1262} /* namespace addon */
1263} /* namespace kodi */
1264
1265#endif /* __cplusplus */