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