summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2017-07-23 16:59:43 +0200
committermanuel <manuel@mausz.at>2017-07-23 16:59:43 +0200
commit4c3251ec645c8b71820dab7e51e612e5919d4e75 (patch)
tree9533268a93e58fc2e16de1b8ee3fafe3784e5225 /xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance
parentf44ecaa4f27e7538ddcad66d40e543bffa2d2d86 (diff)
downloadkodi-pvr-build-4c3251ec645c8b71820dab7e51e612e5919d4e75.tar.gz
kodi-pvr-build-4c3251ec645c8b71820dab7e51e612e5919d4e75.tar.bz2
kodi-pvr-build-4c3251ec645c8b71820dab7e51e612e5919d4e75.zip
sync with upstream
Diffstat (limited to 'xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance')
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDSP.h1288
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h240
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h223
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h163
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h621
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h682
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h668
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h310
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h622
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h256
-rw-r--r--xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h766
11 files changed, 5838 insertions, 1 deletions
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDSP.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDSP.h
new file mode 100644
index 0000000..c508f80
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDSP.h
@@ -0,0 +1,1288 @@
1#pragma once
2
3/*
4 * Copyright (C) 2005-2015 Team Kodi
5 * http://kodi.tv
6 *
7 * This Program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This Program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Kodi; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include "../AddonBase.h"
24
25#define AE_DSP_STREAM_MAX_STREAMS 8
26#define AE_DSP_STREAM_MAX_MODES 32
27
28/*!
29 * @file Addon.h
30 * @section sec1 Basic audio dsp addon interface description
31 * @author Team Kodi
32 * @date 10. May 2014
33 * @version 0.1.5
34 *
35 * @subsection sec1_1 General
36 * @li The basic support on the addon is supplied with the
37 * AE_DSP_ADDON_CAPABILITIES data which becomes asked over
38 * GetCapabilities(...), further the addon must register his available
39 * modes on startup with the RegisterMode(...) callback function.
40 * If one of this two points is not set the addon becomes
41 * ignored for the chain step.
42 *
43 * @subsection sec1_2 Processing
44 * @li On start of new stream the addon becomes called with StreamCreate(...)
45 * to check about given values that it support it basically and can create
46 * his structure, if nothing is supported it can return AE_DSP_ERROR_IGNORE_ME.
47 *
48 * @li As next step StreamIsModeSupported(...) becomes called for every
49 * available and enabled modes, is separated due to more as one available mode
50 * on the addon is possible, if the mode is not supported it can also be return
51 * AE_DSP_ERROR_IGNORE_ME.
52 * - If mode is a resample mode and returns no error it becomes asked with
53 * InputResampleSampleRate(...) or OutputResampleSampleRate(...) (relevant
54 * to his type) about his given sample rate.
55 * - About the from user selected master processing mode the related addon
56 * becomes called now with MasterProcessSetMode(...) to handle it's
57 * selectionon the addon given by the own addon type identifier or by
58 * KODI's useddatabase id, also the currently used stream type (e.g.
59 * Music or Video) is send.
60 * - If the addon supports only one master mode it can ignore this function
61 * and return always AE_DSP_ERROR_NO_ERROR.
62 * - If the master mode is set the addon becomes asked about the from him
63 * given output channel layout related to up- or downmix modes, if
64 * nothing becomes changed on the layout it can return -1.
65 * - The MasterProcessSetMode(...) is also called if from user a another
66 * mode becomes selected.
67 *
68 * @li Then as last step shortly before the first process call becomes executed
69 * the addon is called one time with StreamInitialize(...) to inform that
70 * processing is started on the given settings.
71 * - This function becomes also called on all add-ons if the master process
72 * becomes changed.
73 * - Also every process after StreamInitialize on the addon mode becomes asked
74 * with _..._ProcessNeededSamplesize(...) about required memory size for the
75 * output of his data, if no other size is required it can return 0.
76 *
77 * @li From now the processing becomes handled for the different steps with
78 * _..._Process(...).
79 * - Further it becomes asked with _..._GetDelay(...) about his processing
80 * time as float value in seconds, needed for video and audio alignment.
81 *
82 * @li On the end of the processing if the source becomes stopped the
83 * StreamDestroy(...) function becomes called on all active processing add-ons.
84 *
85 * @note
86 * The StreamCreate(...) can be becomes called for a new stream before the
87 * previous was closed with StreamDestroy(...) ! To have a speed improve.
88 */
89
90namespace kodi { namespace addon { class CInstanceAudioDSP; }}
91
92extern "C" {
93
94 typedef void* ADSPHANDLE;
95
96 typedef unsigned int AE_DSP_STREAM_ID;
97
98 /*!
99 * @brief Audio DSP add-on error codes
100 */
101 typedef enum
102 {
103 AE_DSP_ERROR_NO_ERROR = 0, /*!< @brief no error occurred */
104 AE_DSP_ERROR_UNKNOWN = -1, /*!< @brief an unknown error occurred */
105 AE_DSP_ERROR_IGNORE_ME = -2, /*!< @brief the used input stream can not processed and add-on want to ignore */
106 AE_DSP_ERROR_NOT_IMPLEMENTED = -3, /*!< @brief the method that KODI called is not implemented by the add-on */
107 AE_DSP_ERROR_REJECTED = -4, /*!< @brief the command was rejected by the DSP */
108 AE_DSP_ERROR_INVALID_PARAMETERS = -5, /*!< @brief the parameters of the method that was called are invalid for this operation */
109 AE_DSP_ERROR_INVALID_SAMPLERATE = -6, /*!< @brief the processed samplerate is not supported */
110 AE_DSP_ERROR_INVALID_IN_CHANNELS = -7, /*!< @brief the processed input channel format is not supported */
111 AE_DSP_ERROR_INVALID_OUT_CHANNELS = -8, /*!< @brief the processed output channel format is not supported */
112 AE_DSP_ERROR_FAILED = -9, /*!< @brief the command failed */
113 } AE_DSP_ERROR;
114
115 /*!
116 * @brief The possible DSP channels (used as pointer inside arrays)
117 */
118 typedef enum
119 {
120 AE_DSP_CH_INVALID = -1,
121 AE_DSP_CH_FL = 0,
122 AE_DSP_CH_FR,
123 AE_DSP_CH_FC,
124 AE_DSP_CH_LFE,
125 AE_DSP_CH_BL,
126 AE_DSP_CH_BR,
127 AE_DSP_CH_FLOC,
128 AE_DSP_CH_FROC,
129 AE_DSP_CH_BC,
130 AE_DSP_CH_SL,
131 AE_DSP_CH_SR,
132 AE_DSP_CH_TFL,
133 AE_DSP_CH_TFR,
134 AE_DSP_CH_TFC,
135 AE_DSP_CH_TC,
136 AE_DSP_CH_TBL,
137 AE_DSP_CH_TBR,
138 AE_DSP_CH_TBC,
139 AE_DSP_CH_BLOC,
140 AE_DSP_CH_BROC,
141
142 AE_DSP_CH_MAX
143 } AE_DSP_CHANNEL;
144
145 /*!
146 * @brief Present channel flags
147 */
148 typedef enum
149 {
150 AE_DSP_PRSNT_CH_UNDEFINED = 0,
151 AE_DSP_PRSNT_CH_FL = 1<<AE_DSP_CH_FL,
152 AE_DSP_PRSNT_CH_FR = 1<<AE_DSP_CH_FR,
153 AE_DSP_PRSNT_CH_FC = 1<<AE_DSP_CH_FC,
154 AE_DSP_PRSNT_CH_LFE = 1<<AE_DSP_CH_LFE,
155 AE_DSP_PRSNT_CH_BL = 1<<AE_DSP_CH_BL,
156 AE_DSP_PRSNT_CH_BR = 1<<AE_DSP_CH_BR,
157 AE_DSP_PRSNT_CH_FLOC = 1<<AE_DSP_CH_FLOC,
158 AE_DSP_PRSNT_CH_FROC = 1<<AE_DSP_CH_FROC,
159 AE_DSP_PRSNT_CH_BC = 1<<AE_DSP_CH_BC,
160 AE_DSP_PRSNT_CH_SL = 1<<AE_DSP_CH_SL,
161 AE_DSP_PRSNT_CH_SR = 1<<AE_DSP_CH_SR,
162 AE_DSP_PRSNT_CH_TFL = 1<<AE_DSP_CH_TFL,
163 AE_DSP_PRSNT_CH_TFR = 1<<AE_DSP_CH_TFR,
164 AE_DSP_PRSNT_CH_TFC = 1<<AE_DSP_CH_TFC,
165 AE_DSP_PRSNT_CH_TC = 1<<AE_DSP_CH_TC,
166 AE_DSP_PRSNT_CH_TBL = 1<<AE_DSP_CH_TBL,
167 AE_DSP_PRSNT_CH_TBR = 1<<AE_DSP_CH_TBR,
168 AE_DSP_PRSNT_CH_TBC = 1<<AE_DSP_CH_TBC,
169 AE_DSP_PRSNT_CH_BLOC = 1<<AE_DSP_CH_BLOC,
170 AE_DSP_PRSNT_CH_BROC = 1<<AE_DSP_CH_BROC
171 } AE_DSP_CHANNEL_PRESENT;
172
173 /**
174 * @brief The various stream type formats
175 * Used for audio DSP processing to know input audio type
176 */
177 typedef enum
178 {
179 AE_DSP_ASTREAM_INVALID = -1,
180 AE_DSP_ASTREAM_BASIC = 0,
181 AE_DSP_ASTREAM_MUSIC,
182 AE_DSP_ASTREAM_MOVIE,
183 AE_DSP_ASTREAM_GAME,
184 AE_DSP_ASTREAM_APP,
185 AE_DSP_ASTREAM_PHONE,
186 AE_DSP_ASTREAM_MESSAGE,
187
188 AE_DSP_ASTREAM_AUTO,
189 AE_DSP_ASTREAM_MAX
190 } AE_DSP_STREAMTYPE;
191
192 /*!
193 * @brief Add-ons supported audio stream type flags
194 * used on master mode information on AE_DSP_MODES to know
195 * on which audio stream the master mode is supported
196 */
197 typedef enum
198 {
199 AE_DSP_PRSNT_ASTREAM_BASIC = 1<<AE_DSP_ASTREAM_BASIC,
200 AE_DSP_PRSNT_ASTREAM_MUSIC = 1<<AE_DSP_ASTREAM_MUSIC,
201 AE_DSP_PRSNT_ASTREAM_MOVIE = 1<<AE_DSP_ASTREAM_MOVIE,
202 AE_DSP_PRSNT_ASTREAM_GAME = 1<<AE_DSP_ASTREAM_GAME,
203 AE_DSP_PRSNT_ASTREAM_APP = 1<<AE_DSP_ASTREAM_APP,
204 AE_DSP_PRSNT_ASTREAM_PHONE = 1<<AE_DSP_ASTREAM_PHONE,
205 AE_DSP_PRSNT_ASTREAM_MESSAGE = 1<<AE_DSP_ASTREAM_MESSAGE,
206 } AE_DSP_ASTREAM_PRESENT;
207
208 /**
209 * @brief The various base type formats
210 * Used for audio DSP processing to know input audio source
211 */
212 typedef enum
213 {
214 AE_DSP_ABASE_INVALID = -1,
215 AE_DSP_ABASE_STEREO = 0,
216 AE_DSP_ABASE_MONO,
217 AE_DSP_ABASE_MULTICHANNEL,
218 AE_DSP_ABASE_AC3,
219 AE_DSP_ABASE_EAC3,
220 AE_DSP_ABASE_DTS,
221 AE_DSP_ABASE_DTSHD_MA,
222 AE_DSP_ABASE_DTSHD_HRA,
223 AE_DSP_ABASE_TRUEHD,
224 AE_DSP_ABASE_MLP,
225 AE_DSP_ABASE_FLAC,
226
227 AE_DSP_ABASE_MAX
228 } AE_DSP_BASETYPE;
229
230
231 /**
232 * @brief The from KODI in settings requested audio process quality.
233 * The KODI internal used quality levels is translated to this values
234 * for usage on DSP processing add-ons. Is present on iQualityLevel
235 * inside AE_DSP_SETTINGS.
236 */
237 typedef enum
238 {
239 AE_DSP_QUALITY_UNKNOWN = -1, /*!< @brief Unset, unknown or incorrect quality level */
240 AE_DSP_QUALITY_DEFAULT = 0, /*!< @brief Engine's default quality level */
241
242 /* Basic quality levels */
243 AE_DSP_QUALITY_LOW = 20, /*!< @brief Low quality level */
244 AE_DSP_QUALITY_MID = 30, /*!< @brief Standard quality level */
245 AE_DSP_QUALITY_HIGH = 50, /*!< @brief Best sound processing quality */
246
247 /* Optional quality levels */
248 AE_DSP_QUALITY_REALLYHIGH = 100 /*!< @brief Uncompromising optional quality level, usually with unmeasurable and unnoticeable improvement */
249 } AE_DSP_QUALITY;
250
251 /*!
252 * @brief Audio DSP menu hook categories.
253 * Used to identify on AE_DSP_MENUHOOK given add-on related skin dialog/windows.
254 * Except AE_DSP_MENUHOOK_ALL and AE_DSP_MENUHOOK_SETTING are the menus available
255 * from DSP playback dialogue which can be opened over KODI file context menu and over
256 * button on full screen OSD window.
257 *
258 * Menu hook AE_DSP_MENUHOOK_SETTING is available from DSP processing setup dialogue.
259 */
260 typedef enum
261 {
262 AE_DSP_MENUHOOK_UNKNOWN =-1, /*!< @brief unknown menu hook */
263 AE_DSP_MENUHOOK_ALL = 0, /*!< @brief all categories */
264 AE_DSP_MENUHOOK_PRE_PROCESS = 1, /*!< @brief for pre processing */
265 AE_DSP_MENUHOOK_MASTER_PROCESS = 2, /*!< @brief for master processing */
266 AE_DSP_MENUHOOK_POST_PROCESS = 3, /*!< @brief for post processing */
267 AE_DSP_MENUHOOK_RESAMPLE = 4, /*!< @brief for re sample */
268 AE_DSP_MENUHOOK_MISCELLANEOUS = 5, /*!< @brief for miscellaneous dialogues */
269 AE_DSP_MENUHOOK_INFORMATION = 6, /*!< @brief dialogue to show processing information */
270 AE_DSP_MENUHOOK_SETTING = 7, /*!< @brief for settings */
271 } AE_DSP_MENUHOOK_CAT;
272
273 /*!
274 * @brief Menu hooks that are available in the menus while playing a stream via this add-on.
275 */
276 typedef struct AE_DSP_MENUHOOK
277 {
278 unsigned int iHookId; /*!< @brief (required) this hook's identifier */
279 unsigned int iLocalizedStringId; /*!< @brief (required) the id of the label for this hook in g_localizeStrings */
280 AE_DSP_MENUHOOK_CAT category; /*!< @brief (required) category of menu hook */
281 unsigned int iRelevantModeId; /*!< @brief (required) except category AE_DSP_MENUHOOK_SETTING and AE_DSP_MENUHOOK_ALL must be the related mode id present here */
282 bool bNeedPlayback; /*!< @brief (required) set to true if menu hook need playback and active processing */
283 } ATTRIBUTE_PACKED AE_DSP_MENUHOOK;
284
285 /*!
286 * @brief Audio DSP add-on capabilities. All capabilities are set to "false" as default.
287 * If a capability is set to true, then the corresponding methods from kodi_audiodsp_dll.h need to be implemented.
288 */
289 typedef struct AE_DSP_ADDON_CAPABILITIES
290 {
291 bool bSupportsInputProcess; /*!< @brief true if this add-on provides audio input processing */
292 bool bSupportsInputResample; /*!< @brief true if this add-on provides audio resample before master handling */
293 bool bSupportsPreProcess; /*!< @brief true if this add-on provides audio pre processing */
294 bool bSupportsMasterProcess; /*!< @brief true if this add-on provides audio master processing */
295 bool bSupportsPostProcess; /*!< @brief true if this add-on provides audio post processing */
296 bool bSupportsOutputResample; /*!< @brief true if this add-on provides audio re sample after master handling */
297 } ATTRIBUTE_PACKED AE_DSP_ADDON_CAPABILITIES;
298
299 /*!
300 * @brief Audio processing settings for in and out arrays
301 * Send on creation and before first processed audio packet to add-on
302 */
303 typedef struct AE_DSP_SETTINGS
304 {
305 AE_DSP_STREAM_ID iStreamID; /*!< @brief id of the audio stream packets */
306 AE_DSP_STREAMTYPE iStreamType; /*!< @brief the input stream type source eg, Movie or Music */
307 int iInChannels; /*!< @brief the amount of input channels */
308 unsigned long lInChannelPresentFlags; /*!< @brief the exact channel mapping flags of input */
309 int iInFrames; /*!< @brief the input frame size from KODI */
310 unsigned int iInSamplerate; /*!< @brief the basic sample rate of the audio packet */
311 int iProcessFrames; /*!< @brief the processing frame size inside add-on's */
312 unsigned int iProcessSamplerate; /*!< @brief the sample rate after input resample present in master processing */
313 int iOutChannels; /*!< @brief the amount of output channels */
314 unsigned long lOutChannelPresentFlags; /*!< @brief the exact channel mapping flags for output */
315 int iOutFrames; /*!< @brief the final out frame size for KODI */
316 unsigned int iOutSamplerate; /*!< @brief the final sample rate of the audio packet */
317 bool bInputResamplingActive; /*!< @brief if a re-sampling is performed before master processing this flag is set to true */
318 bool bStereoUpmix; /*!< @brief true if the stereo upmix setting on kodi is set */
319 int iQualityLevel; /*!< @brief the from KODI selected quality level for signal processing */
320 /*!
321 * @note about "iProcessSamplerate" and "iProcessFrames" is set from KODI after call of StreamCreate on input re sample add-on, if re-sampling
322 * and processing is handled inside the same add-on, this value must be ignored!
323 */
324 } ATTRIBUTE_PACKED AE_DSP_SETTINGS;
325
326 /*!
327 * @brief Stream profile properties
328 * Can be used to detect best master processing mode and for post processing methods.
329 */
330//@{
331
332 /*!
333 * @brief Dolby profile types. Given from several formats, e.g. Dolby Digital or TrueHD
334 * Used on AE_DSP_PROFILE_AC3_EAC3 and AE_DSP_PROFILE_MLP_TRUEHD
335 */
336 #define AE_DSP_PROFILE_DOLBY_NONE 0
337 #define AE_DSP_PROFILE_DOLBY_SURROUND 1
338 #define AE_DSP_PROFILE_DOLBY_PLII 2
339 #define AE_DSP_PROFILE_DOLBY_PLIIX 3
340 #define AE_DSP_PROFILE_DOLBY_PLIIZ 4
341 #define AE_DSP_PROFILE_DOLBY_EX 5
342 #define AE_DSP_PROFILE_DOLBY_HEADPHONE 6
343
344 /*!
345 * @brief DTS/DTS HD profile types
346 * Used on AE_DSP_PROFILE_DTS_DTSHD
347 */
348 #define AE_DSP_PROFILE_DTS 0
349 #define AE_DSP_PROFILE_DTS_ES 1
350 #define AE_DSP_PROFILE_DTS_96_24 2
351 #define AE_DSP_PROFILE_DTS_HD_HRA 3
352 #define AE_DSP_PROFILE_DTS_HD_MA 4
353
354 /*!
355 * @brief AC3/EAC3 based service types
356 * Used on AE_DSP_PROFILE_AC3_EAC3
357 */
358 #define AE_DSP_SERVICE_TYPE_MAIN 0
359 #define AE_DSP_SERVICE_TYPE_EFFECTS 1
360 #define AE_DSP_SERVICE_TYPE_VISUALLY_IMPAIRED 2
361 #define AE_DSP_SERVICE_TYPE_HEARING_IMPAIRED 3
362 #define AE_DSP_SERVICE_TYPE_DIALOGUE 4
363 #define AE_DSP_SERVICE_TYPE_COMMENTARY 5
364 #define AE_DSP_SERVICE_TYPE_EMERGENCY 6
365 #define AE_DSP_SERVICE_TYPE_VOICE_OVER 7
366 #define AE_DSP_SERVICE_TYPE_KARAOKE 8
367
368 /*!
369 * @brief AC3/EAC3 based room types
370 * Present on AE_DSP_PROFILE_AC3_EAC3 and can be used for frequency corrections
371 * at post processing, e.g. THX Re-Equalization
372 */
373 #define AE_DSP_ROOM_TYPE_UNDEFINED 0
374 #define AE_DSP_ROOM_TYPE_SMALL 1
375 #define AE_DSP_ROOM_TYPE_LARGE 2
376
377 /*!
378 * @brief AC3/EAC3 stream profile properties
379 */
380 //! @todo add handling for it (currently never becomes set)
381 typedef struct AE_DSP_PROFILE_AC3_EAC3
382 {
383 unsigned int iProfile; /*!< defined by AE_DSP_PROFILE_DOLBY_* */
384 unsigned int iServiceType; /*!< defined by AE_DSP_SERVICE_TYPE_* */
385 unsigned int iRoomType; /*!< defined by AE_DSP_ROOM_TYPE_* (NOTICE: Information about it currently not supported from ffmpeg and must be implemented) */
386 } ATTRIBUTE_PACKED AE_DSP_PROFILE_AC3_EAC3;
387
388 /*!
389 * @brief MLP/Dolby TrueHD stream profile properties
390 */
391 //! @todo add handling for it (currently never becomes set)
392 typedef struct AE_DSP_PROFILE_MLP_TRUEHD
393 {
394 unsigned int iProfile; /*!< defined by AE_DSP_PROFILE_DOLBY_* */
395 } ATTRIBUTE_PACKED AE_DSP_PROFILE_MLP_TRUEHD;
396
397 /*!
398 * @brief DTS/DTS HD stream profile properties
399 */
400 //! @todo add handling for it (currently never becomes set)
401 typedef struct AE_DSP_PROFILE_DTS_DTSHD
402 {
403 unsigned int iProfile; /*!< defined by AE_DSP_PROFILE_DTS* */
404 bool bSurroundMatrix; /*!< if set to true given 2.0 stream is surround encoded */
405 } ATTRIBUTE_PACKED AE_DSP_PROFILE_DTS_DTSHD;
406
407 union AE_DSP_PROFILE
408 {
409 AE_DSP_PROFILE_AC3_EAC3 ac3_eac3; /*!< Dolby Digital/Digital+ profile data */
410 AE_DSP_PROFILE_MLP_TRUEHD mlp_truehd; /*!< MLP or Dolby TrueHD profile data */
411 AE_DSP_PROFILE_DTS_DTSHD dts_dtshd; /*!< DTS/DTS-HD profile data */
412 };
413 //@}
414
415 /*!
416 * @brief Audio DSP stream properties
417 * Used to check for the DSP add-on that the stream is supported,
418 * as example Dolby Digital Ex processing is only required on Dolby Digital with 5.1 layout
419 */
420 typedef struct AE_DSP_STREAM_PROPERTIES
421 {
422 AE_DSP_STREAM_ID iStreamID; /*!< @brief stream id of the audio stream packets */
423 AE_DSP_STREAMTYPE iStreamType; /*!< @brief the input stream type source eg, Movie or Music */
424 int iBaseType; /*!< @brief the input stream base type source eg, Dolby Digital */
425 const char* strName; /*!< @brief the audio stream name */
426 const char* strCodecId; /*!< @brief codec id string of the audio stream */
427 const char* strLanguage; /*!< @brief language id of the audio stream */
428 int iIdentifier; /*!< @brief audio stream id inside player */
429 int iChannels; /*!< @brief amount of basic channels */
430 int iSampleRate; /*!< @brief sample rate */
431 AE_DSP_PROFILE Profile; /*!< @brief current running stream profile data */
432 } ATTRIBUTE_PACKED AE_DSP_STREAM_PROPERTIES;
433
434 /*!
435 * @brief Audio DSP mode categories
436 */
437 typedef enum
438 {
439 AE_DSP_MODE_TYPE_UNDEFINED = -1, /*!< @brief undefined type, never be used from add-on! */
440 AE_DSP_MODE_TYPE_INPUT_RESAMPLE = 0, /*!< @brief for input re sample */
441 AE_DSP_MODE_TYPE_PRE_PROCESS = 1, /*!< @brief for preprocessing */
442 AE_DSP_MODE_TYPE_MASTER_PROCESS = 2, /*!< @brief for master processing */
443 AE_DSP_MODE_TYPE_POST_PROCESS = 3, /*!< @brief for post processing */
444 AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE = 4, /*!< @brief for output re sample */
445 AE_DSP_MODE_TYPE_MAX = 5
446 } AE_DSP_MODE_TYPE;
447
448 /*!
449 * @brief Audio DSP master mode information
450 * Used to get all available modes for current input stream
451 */
452 typedef struct AE_DSP_MODES
453 {
454 unsigned int iModesCount; /*!< @brief (required) count of how much modes are in AE_DSP_MODES */
455 struct AE_DSP_MODE
456 {
457 int iUniqueDBModeId; /*!< @brief (required) the inside add-on used identifier for the mode, set by KODI's audio DSP database */
458 AE_DSP_MODE_TYPE iModeType; /*!< @brief (required) the processong mode type, see AE_DSP_MODE_TYPE */
459 char strModeName[ADDON_STANDARD_STRING_LENGTH]; /*!< @brief (required) the addon name of the mode, used on KODI's logs */
460
461 unsigned int iModeNumber; /*!< @brief (required) number of this mode on the add-on, is used on process functions with value "mode_id" */
462 unsigned int iModeSupportTypeFlags; /*!< @brief (required) flags about supported input types for this mode, see AE_DSP_ASTREAM_PRESENT */
463 bool bHasSettingsDialog; /*!< @brief (required) if setting dialog(s) are available it must be set to true */
464 bool bIsDisabled; /*!< @brief (optional) true if this mode is marked as disabled and not enabled default, only relevant for master processes, all other types always disabled as default */
465
466 unsigned int iModeName; /*!< @brief (required) the name id of the mode for this hook in g_localizeStrings */
467 unsigned int iModeSetupName; /*!< @brief (optional) the name id of the mode inside settings for this hook in g_localizeStrings */
468 unsigned int iModeDescription; /*!< @brief (optional) the description id of the mode for this hook in g_localizeStrings */
469 unsigned int iModeHelp; /*!< @brief (optional) help string id for inside DSP settings dialog of the mode for this hook in g_localizeStrings */
470
471 char strOwnModeImage[ADDON_STANDARD_STRING_LENGTH]; /*!< @brief (optional) flag image for the mode */
472 char strOverrideModeImage[ADDON_STANDARD_STRING_LENGTH];/*!< @brief (optional) image to override KODI Image for the mode, eg. Dolby Digital with Dolby Digital Ex (only used on master modes) */
473 } mode[AE_DSP_STREAM_MAX_MODES]; /*!< @brief Modes array storage */
474 } ATTRIBUTE_PACKED AE_DSP_MODES;
475
476 /*!
477 * @brief Audio DSP menu hook data
478 */
479 typedef struct AE_DSP_MENUHOOK_DATA
480 {
481 AE_DSP_MENUHOOK_CAT category; /*!< @brief (required) related menuhook data category */
482 union data {
483 AE_DSP_STREAM_ID iStreamId; /*!< @brief currently only stream id is used, is used as union to have extension possibility */
484 } data; /*!< @brief related category related data */
485 } ATTRIBUTE_PACKED AE_DSP_MENUHOOK_DATA;
486
487 /*!
488 * @brief Properties passed to the Create() method of an add-on.
489 */
490 typedef struct AddonProps_AudioDSP
491 {
492 const char* strUserPath; /*!< @brief path to the user profile */
493 const char* strAddonPath; /*!< @brief path to this add-on */
494 } AddonProps_AudioDSP;
495
496 typedef struct AddonToKodiFuncTable_AudioDSP
497 {
498 void* kodiInstance;
499 void (*add_menu_hook)(void* kodiInstance, AE_DSP_MENUHOOK *hook);
500 void (*remove_menu_hook)(void* kodiInstance, AE_DSP_MENUHOOK *hook);
501 void (*register_mode)(void* kodiInstance, AE_DSP_MODES::AE_DSP_MODE *mode);
502 void (*unregister_mode)(void* kodiInstance, AE_DSP_MODES::AE_DSP_MODE *mode);
503 } AddonToKodiFuncTable_AudioDSP;
504
505 struct AddonInstance_AudioDSP;
506 typedef struct KodiToAddonFuncTable_AudioDSP
507 {
508 kodi::addon::CInstanceAudioDSP* addonInstance;
509 void (__cdecl* get_capabilities)(AddonInstance_AudioDSP const* addonInstance, AE_DSP_ADDON_CAPABILITIES*);
510 const char* (__cdecl* get_dsp_name)(AddonInstance_AudioDSP const* addonInstance);
511 const char* (__cdecl* get_dsp_version)(AddonInstance_AudioDSP const* addonInstance);
512 AE_DSP_ERROR (__cdecl* menu_hook)(AddonInstance_AudioDSP const* addonInstance, const AE_DSP_MENUHOOK*, const AE_DSP_MENUHOOK_DATA*);
513
514 AE_DSP_ERROR (__cdecl* stream_create)(AddonInstance_AudioDSP const* addonInstance, const AE_DSP_SETTINGS*, const AE_DSP_STREAM_PROPERTIES*, ADDON_HANDLE);
515 AE_DSP_ERROR (__cdecl* stream_destroy)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
516 AE_DSP_ERROR (__cdecl* stream_is_mode_supported)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, AE_DSP_MODE_TYPE, unsigned int, int);
517 AE_DSP_ERROR (__cdecl* stream_initialize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, const AE_DSP_SETTINGS*);
518
519 bool (__cdecl* input_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, const float**, unsigned int);
520
521 unsigned int (__cdecl* input_resample_process_needed_samplesize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
522 unsigned int (__cdecl* input_resample_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, const float**, float**, unsigned int);
523 float (__cdecl* input_resample_get_delay)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
524 int (__cdecl* input_resample_samplerate)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
525
526 unsigned int (__cdecl* pre_process_needed_samplesize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int);
527 float (__cdecl* pre_process_get_delay)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int);
528 unsigned int (__cdecl* pre_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int, const float**, float**, unsigned int);
529
530 AE_DSP_ERROR (__cdecl* master_process_set_mode)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, AE_DSP_STREAMTYPE, unsigned int, int);
531 unsigned int (__cdecl* master_process_needed_samplesize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
532 float (__cdecl* master_process_get_delay)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
533 int (__cdecl* master_process_get_out_channels)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned long*);
534 unsigned int (__cdecl* master_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, const float**, float**, unsigned int);
535 const char* (__cdecl* master_process_get_stream_info_string)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
536
537 unsigned int (__cdecl* post_process_needed_samplesize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int);
538 float (__cdecl* post_process_get_delay)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int);
539 unsigned int (__cdecl* post_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, unsigned int, const float**, float**, unsigned int);
540
541 unsigned int (__cdecl* output_resample_process_needed_samplesize)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
542 unsigned int (__cdecl* output_resample_process)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE, const float**, float**, unsigned int);
543 float (__cdecl* output_resample_get_delay)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
544 int (__cdecl* output_resample_samplerate)(AddonInstance_AudioDSP const* addonInstance, const ADDON_HANDLE);
545 } KodiToAddonFuncTable_AudioDSP;
546
547 typedef struct AddonInstance_AudioDSP
548 {
549 AddonProps_AudioDSP props;
550 AddonToKodiFuncTable_AudioDSP toKodi;
551 KodiToAddonFuncTable_AudioDSP toAddon;
552 } AddonInstance_AudioDSP;
553
554} /* extern "C" */
555
556namespace kodi {
557namespace addon {
558
559 class CInstanceAudioDSP : public IAddonInstance
560 {
561 public:
562 //==========================================================================
563 /// @brief Class constructor
564 ///
565 CInstanceAudioDSP()
566 : IAddonInstance(ADDON_INSTANCE_ADSP)
567 {
568 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
569 throw std::logic_error("kodi::addon::CInstanceAudioDSP: Creation of more as one in single instance way is not allowed!");
570
571 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance);
572 CAddonBase::m_interface->globalSingleInstance = this;
573 }
574 //--------------------------------------------------------------------------
575
576 //==========================================================================
577 /// @brief Class constructor
578 ///
579 /// @param[in] instance The from Kodi given instance given be
580 /// add-on CreateInstance call with instance
581 /// id ADDON_INSTANCE_ADSP.
582 ///
583 CInstanceAudioDSP(KODI_HANDLE instance)
584 : IAddonInstance(ADDON_INSTANCE_ADSP)
585 {
586 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
587 throw std::logic_error("kodi::addon::CInstanceAudioDSP: Creation of multiple together with single instance way is not allowed!");
588
589 SetAddonStruct(instance);
590 }
591 //--------------------------------------------------------------------------
592
593 /*! @name Audio DSP add-on methods */
594 //@{
595 //==========================================================================
596 ///
597 /// @brief Get the list of features that this add-on provides.
598 /// Called by KODI to query the add-ons capabilities.
599 /// Used to check which options should be presented in the DSP, which methods
600 /// to call, etc.
601 /// All capabilities that the add-on supports should be set to true.
602 /// @param capabilities The add-ons capabilities.
603 /// @remarks Valid implementation required.
604 ///
605 virtual void GetCapabilities(AE_DSP_ADDON_CAPABILITIES& capabilities) = 0;
606 //--------------------------------------------------------------------------
607
608 //==========================================================================
609 ///
610 /// @return The name reported by the back end that will be displayed in the
611 /// UI.
612 /// @remarks Valid implementation required.
613 ///
614 virtual std::string GetDSPName() = 0;
615 //--------------------------------------------------------------------------
616
617 //==========================================================================
618 ///
619 /// @return The version string reported by the back end that will be displayed
620 /// in the UI.
621 /// @remarks Valid implementation required.
622 ///
623 virtual std::string GetDSPVersion() = 0;
624 //--------------------------------------------------------------------------
625
626 //==========================================================================
627 ///
628 /// @brief Call one of the menu hooks (if supported).
629 /// Supported AE_DSP_MENUHOOK instances have to be added in ADDON_Create(),
630 /// by calling AddMenuHook() on the callback.
631 /// @param menuhook The hook to call.
632 /// @param item The selected item for which the hook was called.
633 /// @return AE_DSP_ERROR_NO_ERROR if the hook was called successfully.
634 /// @remarks Optional. Return AE_DSP_ERROR_NOT_IMPLEMENTED if this add-on
635 /// won't provide this function.
636 ///
637 virtual AE_DSP_ERROR MenuHook(const AE_DSP_MENUHOOK& menuhook, const AE_DSP_MENUHOOK_DATA& item) { return AE_DSP_ERROR_NOT_IMPLEMENTED; }
638 //--------------------------------------------------------------------------
639 //@}
640
641 //==========================================================================
642 /// @name DSP processing control, used to open and close a stream
643 /// @remarks Valid implementation required.
644 ///
645 //@{
646 ///
647 /// @brief Set up Audio DSP with selected audio settings (use the basic
648 /// present audio stream data format).
649 /// Used to detect available add-ons for present stream, as example stereo
650 /// surround upmix not needed on 5.1 audio stream.
651 /// @param addonSettings The add-ons audio settings.
652 /// @param properties The properties of the currently playing stream.
653 /// @param handle On this becomes addon informated about stream id and can set function addresses which need on calls
654 /// @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully
655 /// and data can be performed. AE_DSP_ERROR_IGNORE_ME if format is not
656 /// supported, but without fault.
657 /// @remarks Valid implementation required.
658 ///
659 virtual AE_DSP_ERROR StreamCreate(const AE_DSP_SETTINGS& addonSettings, const AE_DSP_STREAM_PROPERTIES& properties, ADDON_HANDLE handle) = 0;
660 //--------------------------------------------------------------------------
661
662 //==========================================================================
663 ///
664 /// Remove the selected id from currently used DSP processes
665 /// @param handle identification data for stream
666 /// @return AE_DSP_ERROR_NO_ERROR if the becomes found and removed
667 /// @remarks Valid implementation required.
668 ///
669 virtual AE_DSP_ERROR StreamDestroy(const ADDON_HANDLE handle) = 0;
670 //--------------------------------------------------------------------------
671
672 //==========================================================================
673 ///
674 /// @brief Ask the add-on about a requested processing mode that it is
675 /// supported on the current stream. Is called about every add-on mode after
676 /// successed StreamCreate.
677 /// @param handle identification data for stream
678 /// @param type The processing mode type, see AE_DSP_MODE_TYPE for definitions
679 /// @param mode_id The mode inside add-on which must be performed on call. Id
680 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
681 /// RegisterMode callback,
682 /// @param unique_db_mode_id The Mode unique id generated from dsp database.
683 /// @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully
684 /// or if the stream is not supported the add-on must return
685 /// AE_DSP_ERROR_IGNORE_ME.
686 /// @remarks Valid implementation required.
687 ///
688 virtual AE_DSP_ERROR StreamIsModeSupported(const ADDON_HANDLE handle, AE_DSP_MODE_TYPE type, unsigned int mode_id, int unique_db_mode_id) = 0;
689 //--------------------------------------------------------------------------
690
691 //==========================================================================
692 ///
693 /// @brief Set up Audio DSP with selected audio settings (detected on data of
694 /// first present audio packet)
695 /// @param addonSettings The add-ons audio settings.
696 /// @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully.
697 /// @remarks Valid implementation required.
698 ///
699 virtual AE_DSP_ERROR StreamInitialize(const ADDON_HANDLE handle, const AE_DSP_SETTINGS& addonSettings) = 0;
700 //--------------------------------------------------------------------------
701
702 //@}
703
704 /// @name DSP input processing
705 /// @remarks Only used by KODI if bSupportsInputProcess is set to true.
706 ///
707 //@{
708 //==========================================================================
709 ///
710 /// @brief DSP input processing
711 /// Can be used to have unchanged stream..
712 /// All DSP add-ons allowed to-do this.
713 /// @param handle identification data for stream
714 /// @param array_in Pointer to data memory
715 /// @param samples Amount of samples inside array_in
716 /// @return true if work was OK
717 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
718 /// GetCapabilities
719 ///
720 virtual bool InputProcess(const ADDON_HANDLE handle, const float** array_in, unsigned int samples) { return true; }
721 //--------------------------------------------------------------------------
722 //@}
723
724 /// @name DSP pre-resampling
725 /// @remarks Only used by KODI if bSupportsInputResample is set to true.
726 ///
727 //@{
728 //==========================================================================
729 ///
730 /// @brief If the add-on operate with buffered arrays and the output size can
731 /// be higher as the input it becomes asked about needed size before any
732 /// InputResampleProcess call.
733 /// @param handle identification data for stream
734 /// @return The needed size of output array or 0 if no changes within it
735 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
736 /// GetCapabilities
737 ///
738 virtual unsigned int InputResampleProcessNeededSamplesize(const ADDON_HANDLE handle) { return 0; }
739 //--------------------------------------------------------------------------
740
741 //==========================================================================
742 ///
743 /// @brief DSP re sample processing before master.
744 /// Here a high quality resample can be performed.
745 /// Only one DSP add-on is allowed to-do this!
746 /// @param handle identification data for stream
747 /// @param array_in Pointer to input data memory
748 /// @param array_out Pointer to output data memory
749 /// @param samples Amount of samples inside array_in
750 /// @return Amount of samples processed
751 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
752 /// GetCapabilities
753 ///
754 virtual unsigned int InputResampleProcess(const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples) { return 0; }
755 //--------------------------------------------------------------------------
756
757 //==========================================================================
758 ///
759 /// @brief Returns the re-sampling generated new sample rate used before the
760 /// master process
761 /// @param handle identification data for stream
762 /// @return The new sample rate
763 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
764 /// GetCapabilities
765 ///
766 virtual int InputResampleSampleRate(const ADDON_HANDLE handle) { return 0; }
767 //--------------------------------------------------------------------------
768
769 //==========================================================================
770 ///
771 /// @brief Returns the time in seconds that it will take
772 /// for the next added packet to be returned to KODI.
773 /// @param handle identification data for stream
774 /// @return the delay in seconds
775 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
776 /// GetCapabilities
777 ///
778 virtual float InputResampleGetDelay(const ADDON_HANDLE handle) { return 0.0f; }
779 //--------------------------------------------------------------------------
780 //@}
781
782 /** @name DSP Pre processing
783 * @remarks Only used by KODI if bSupportsPreProcess is set to true.
784 */
785 //@{
786 //==========================================================================
787 ///
788 /// @brief If the addon operate with buffered arrays and the output size can
789 /// be higher as the input it becomes asked about needed size before any
790 /// PreProcess call.
791 /// @param handle identification data for stream
792 /// @param mode_id The mode inside add-on which must be performed on call. Id
793 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
794 /// RegisterMode callback and can be defined from add-on as a structure
795 /// pointer or anything else what is needed to find it.
796 /// @return The needed size of output array or 0 if no changes within it
797 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
798 /// GetCapabilities
799 ///
800 virtual unsigned int PreProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id) { return 0; }
801 //--------------------------------------------------------------------------
802
803 //==========================================================================
804 ///
805 /// @brief Returns the time in seconds that it will take
806 /// for the next added packet to be returned to KODI.
807 /// @param handle identification data for stream
808 /// @param mode_id The mode inside add-on which must be performed on call. Id
809 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
810 /// RegisterMode callback and can be defined from add-on as a structure
811 /// pointer or anything else what is needed to find it.
812 /// @return the delay in seconds
813 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
814 /// GetCapabilities
815 ///
816 virtual float PreProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id) { return 0.0f; }
817 //--------------------------------------------------------------------------
818
819 //==========================================================================
820 ///
821 /// @brief DSP preprocessing
822 /// All DSP add-ons allowed to-do this.
823 /// @param handle identification data for stream
824 /// @param mode_id The mode inside add-on which must be performed on call. Id
825 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
826 /// RegisterMode callback and can be defined from add-on as a structure
827 /// pointer or anything else what is needed to find it.
828 /// @param array_in Pointer to input data memory
829 /// @param array_out Pointer to output data memory
830 /// @param samples Amount of samples inside array_in
831 /// @return Amount of samples processed
832 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
833 /// GetCapabilities
834 ///
835 virtual unsigned int PreProcess(const ADDON_HANDLE handle, unsigned int mode_id, const float** array_in, float** array_out, unsigned int samples) { return 0; }
836 //--------------------------------------------------------------------------
837 //@}
838
839 /** @name DSP Master processing
840 * @remarks Only used by KODI if bSupportsMasterProcess is set to true.
841 */
842 //@{
843 //==========================================================================
844 ///
845 /// @brief Set the active master process mode
846 /// @param handle identification data for stream
847 /// @param type Requested stream type for the selected master mode
848 /// @param mode_id The Mode identifier.
849 /// @param unique_db_mode_id The Mode unique id generated from DSP database.
850 /// @return AE_DSP_ERROR_NO_ERROR if the setup was successful
851 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
852 /// GetCapabilities
853 ///
854 virtual AE_DSP_ERROR MasterProcessSetMode(const ADDON_HANDLE handle, AE_DSP_STREAMTYPE type, unsigned int mode_id, int unique_db_mode_id) { return AE_DSP_ERROR_NOT_IMPLEMENTED; }
855 //--------------------------------------------------------------------------
856
857 //==========================================================================
858 ///
859 /// @brief If the add-on operate with buffered arrays and the output size can
860 /// be higher as the input it becomes asked about needed size before any
861 /// MasterProcess call.
862 /// @param handle identification data for stream
863 /// @return The needed size of output array or 0 if no changes within it
864 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
865 /// GetCapabilities
866 ///
867 virtual unsigned int MasterProcessNeededSamplesize(const ADDON_HANDLE handle) { return 0; }
868 //--------------------------------------------------------------------------
869
870 //==========================================================================
871 ///
872 /// @brief Returns the time in seconds that it will take
873 /// for the next added packet to be returned to KODI.
874 /// @param handle identification data for stream
875 /// @return the delay in seconds
876 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
877 /// GetCapabilities
878 ///
879 virtual float MasterProcessGetDelay(const ADDON_HANDLE handle) { return 0.0f; }
880 //--------------------------------------------------------------------------
881
882 //==========================================================================
883 ///
884 /// @brief Returns the from selected master mode performed channel alignment
885 /// @param handle identification data for stream
886 /// @retval out_channel_present_flags the exact channel present flags after
887 /// performed up-/downmix
888 /// @return the amount channels
889 /// @remarks Optional. Must be used and set if a channel up- or downmix is
890 /// processed from the active master mode
891 ///
892 virtual int MasterProcessGetOutChannels(const ADDON_HANDLE handle, unsigned long& out_channel_present_flags) { return 0; }
893 //--------------------------------------------------------------------------
894
895 //==========================================================================
896 ///
897 /// @brief Master processing becomes performed with it
898 /// Here a channel up-mix/down-mix for stereo surround sound can be performed
899 /// Only one DSP add-on is allowed to-do this!
900 /// @param handle identification data for stream
901 /// @param array_in Pointer to input data memory
902 /// @param array_out Pointer to output data memory
903 /// @param samples Amount of samples inside array_in
904 /// @return Amount of samples processed
905 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
906 /// GetCapabilities
907 ///
908 virtual unsigned int MasterProcess(const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples) { return 0; }
909 //--------------------------------------------------------------------------
910
911 //==========================================================================
912 ///
913 /// Used to get a information string about the processed work to show on skin
914 /// @return A string to show
915 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
916 /// GetCapabilities
917 ///
918 virtual std::string MasterProcessGetStreamInfoString(const ADDON_HANDLE handle) { return ""; }
919 //--------------------------------------------------------------------------
920 //@}
921
922 /** @name DSP Post processing
923 * @remarks Only used by KODI if bSupportsPostProcess is set to true.
924 */
925 //@{
926 //==========================================================================
927 ///
928 /// If the add-on operate with buffered arrays and the output size can be
929 /// higher as the input it becomes asked about needed size before any
930 /// PostProcess call.
931 /// @param handle identification data for stream
932 /// @param mode_id The mode inside add-on which must be performed on call. Id
933 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
934 /// RegisterMode callback, and can be defined from add-on as a structure
935 /// pointer or anything else what is needed to find it.
936 /// @return The needed size of output array or 0 if no changes within it
937 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
938 /// GetCapabilities
939 ///
940 virtual unsigned int PostProcessNeededSamplesize(const ADDON_HANDLE handle, unsigned int mode_id) { return 0; }
941 //--------------------------------------------------------------------------
942
943 //==========================================================================
944 ///
945 /// Returns the time in seconds that it will take
946 /// for the next added packet to be returned to KODI.
947 /// @param handle identification data for stream
948 /// @param mode_id The mode inside add-on which must be performed on call. Id
949 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
950 /// RegisterMode callback, and can be defined from add-on as a structure
951 /// pointer or anything else what is needed to find it.
952 /// @return the delay in seconds
953 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
954 /// GetCapabilities
955 ///
956 virtual float PostProcessGetDelay(const ADDON_HANDLE handle, unsigned int mode_id) { return 0.0f; }
957 //--------------------------------------------------------------------------
958
959 //==========================================================================
960
961 ///
962 /// @brief DSP post processing
963 /// On the post processing can be things performed with additional channel
964 /// upmix like 6.1 to 7.1
965 /// or frequency/volume corrections, speaker distance handling, equalizer... .
966 /// All DSP add-ons allowed to-do this.
967 /// @param handle identification data for stream
968 /// @param mode_id The mode inside add-on which must be performed on call. Id
969 /// is set from add-on by iModeNumber on AE_DSP_MODE structure during
970 /// RegisterMode callback, and can be defined from add-on as a structure
971 /// pointer or anything else what is needed to find it.
972 /// @param array_in Pointer to input data memory
973 /// @param array_out Pointer to output data memory
974 /// @param samples Amount of samples inside array_in
975 /// @return Amount of samples processed
976 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
977 /// GetCapabilities
978 ///
979 virtual unsigned int PostProcess(const ADDON_HANDLE handle, unsigned int mode_id, const float** array_in, float** array_out, unsigned int samples) { return 0; }
980
981 //--------------------------------------------------------------------------
982 //@}
983
984 /** @name DSP Post re-sampling
985 * @remarks Only used by KODI if bSupportsOutputResample is set to true.
986 */
987 //@{
988 //==========================================================================
989 ///
990 /// @brief If the add-on operate with buffered arrays and the output size
991 /// can be higher as the input
992 /// it becomes asked about needed size before any OutputResampleProcess call.
993 /// @param handle identification data for stream
994 /// @return The needed size of output array or 0 if no changes within it
995 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
996 /// GetCapabilities
997 ///
998 virtual unsigned int OutputResampleProcessNeededSamplesize(const ADDON_HANDLE handle) { return 0; }
999 //--------------------------------------------------------------------------
1000
1001 //==========================================================================
1002 ///
1003 /// @brief Re-sampling after master processing becomes performed with it if
1004 /// needed, only
1005 /// one add-on can perform it.
1006 /// @param handle identification data for stream
1007 /// @param array_in Pointer to input data memory
1008 /// @param array_out Pointer to output data memory
1009 /// @param samples Amount of samples inside array_in
1010 /// @return Amount of samples processed
1011 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
1012 /// GetCapabilities
1013 ///
1014 virtual unsigned int OutputResampleProcess(const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples) { return 0; }
1015 //--------------------------------------------------------------------------
1016
1017 //==========================================================================
1018 ///
1019 /// @brief Returns the re-sampling generated new sample rate used after the
1020 /// master process.
1021 /// @param handle identification data for stream
1022 /// @return The new sample rate
1023 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
1024 /// GetCapabilities
1025 ///
1026 virtual int OutputResampleSampleRate(const ADDON_HANDLE handle) { return 0; }
1027 //--------------------------------------------------------------------------
1028
1029 //==========================================================================
1030 ///
1031 /// @brief Returns the time in seconds that it will take for the next added
1032 /// packet to be returned to KODI.
1033 /// @param handle identification data for stream
1034 /// @return the delay in seconds
1035 /// @remarks Optional. Is set by AE_DSP_ADDON_CAPABILITIES and asked with
1036 /// GetCapabilities
1037 ///
1038 virtual float OutputResampleGetDelay(const ADDON_HANDLE handle) { return 0.0f; }
1039 //--------------------------------------------------------------------------
1040 //@}
1041
1042 //==========================================================================
1043 ///
1044 /// @brief Add or replace a menu hook for the context menu for this add-on
1045 /// @param hook The hook to add
1046 ///
1047 void AddMenuHook(AE_DSP_MENUHOOK* hook)
1048 {
1049 return m_instanceData->toKodi.add_menu_hook(m_instanceData->toKodi.kodiInstance, hook);
1050 }
1051 //--------------------------------------------------------------------------
1052
1053 //==========================================================================
1054 ///
1055 /// @brief Remove a menu hook for the context menu for this add-on
1056 /// @param hook The hook to remove
1057 ///
1058 void RemoveMenuHook(AE_DSP_MENUHOOK* hook)
1059 {
1060 return m_instanceData->toKodi.remove_menu_hook(m_instanceData->toKodi.kodiInstance, hook);
1061 }
1062 //--------------------------------------------------------------------------
1063
1064 //==========================================================================
1065 ///
1066 /// @brief Add or replace master mode information inside audio dsp database.
1067 /// Becomes identifier written inside mode to iModeID if it was 0 (undefined)
1068 /// @param mode The master mode to add or update inside database
1069 ///
1070 void RegisterMode(AE_DSP_MODES::AE_DSP_MODE* mode)
1071 {
1072 return m_instanceData->toKodi.register_mode(m_instanceData->toKodi.kodiInstance, mode);
1073 }
1074 //--------------------------------------------------------------------------
1075
1076 //==========================================================================
1077 ///
1078 /// @brief Remove a master mode from audio dsp database
1079 /// @param mode The Mode to remove
1080 ///
1081 void UnregisterMode(AE_DSP_MODES::AE_DSP_MODE* mode)
1082 {
1083 return m_instanceData->toKodi.unregister_mode(m_instanceData->toKodi.kodiInstance, mode);
1084 }
1085 //--------------------------------------------------------------------------
1086
1087 private:
1088 void SetAddonStruct(KODI_HANDLE instance)
1089 {
1090 if (instance == nullptr)
1091 throw std::logic_error("kodi::addon::CInstanceAudioDSP: Null pointer instance passed.");
1092
1093 m_instanceData = static_cast<AddonInstance_AudioDSP*>(instance);
1094
1095 m_instanceData->toAddon.get_capabilities = ADDON_GetCapabilities;
1096 m_instanceData->toAddon.get_dsp_name = ADDON_GetDSPName;
1097 m_instanceData->toAddon.get_dsp_version = ADDON_GetDSPVersion;
1098 m_instanceData->toAddon.menu_hook = ADDON_MenuHook;
1099
1100 m_instanceData->toAddon.stream_create = ADDON_StreamCreate;
1101 m_instanceData->toAddon.stream_destroy = ADDON_StreamDestroy;
1102 m_instanceData->toAddon.stream_is_mode_supported = ADDON_StreamIsModeSupported;
1103 m_instanceData->toAddon.stream_initialize = ADDON_StreamInitialize;
1104
1105 m_instanceData->toAddon.input_process = ADDON_InputProcess;
1106
1107 m_instanceData->toAddon.input_resample_process_needed_samplesize = ADDON_InputResampleProcessNeededSamplesize;
1108 m_instanceData->toAddon.input_resample_process = ADDON_InputResampleProcess;
1109 m_instanceData->toAddon.input_resample_get_delay = ADDON_InputResampleGetDelay;
1110 m_instanceData->toAddon.input_resample_samplerate = ADDON_InputResampleSampleRate;
1111
1112 m_instanceData->toAddon.pre_process_needed_samplesize = ADDON_PreProcessNeededSamplesize;
1113 m_instanceData->toAddon.pre_process_get_delay = ADDON_PreProcessGetDelay;
1114 m_instanceData->toAddon.pre_process = ADDON_PreProcess;
1115
1116 m_instanceData->toAddon.master_process_set_mode = ADDON_MasterProcessSetMode;
1117 m_instanceData->toAddon.master_process_needed_samplesize = ADDON_MasterProcessNeededSamplesize;
1118 m_instanceData->toAddon.master_process_get_delay = ADDON_MasterProcessGetDelay;
1119 m_instanceData->toAddon.master_process_get_out_channels = ADDON_MasterProcessGetOutChannels;
1120 m_instanceData->toAddon.master_process = ADDON_MasterProcess;
1121 m_instanceData->toAddon.master_process_get_stream_info_string = ADDON_MasterProcessGetStreamInfoString;
1122
1123 m_instanceData->toAddon.post_process_needed_samplesize = ADDON_PostProcessNeededSamplesize;
1124 m_instanceData->toAddon.post_process_get_delay = ADDON_PostProcessGetDelay;
1125 m_instanceData->toAddon.post_process = ADDON_PostProcess;
1126
1127 m_instanceData->toAddon.output_resample_process_needed_samplesize = ADDON_OutputResampleProcessNeededSamplesize;
1128 m_instanceData->toAddon.output_resample_process = ADDON_OutputResampleProcess;
1129 m_instanceData->toAddon.output_resample_get_delay = ADDON_OutputResampleGetDelay;
1130 m_instanceData->toAddon.output_resample_samplerate = ADDON_OutputResampleSampleRate;
1131 }
1132
1133 static inline void ADDON_GetCapabilities(AddonInstance_AudioDSP const* instance, AE_DSP_ADDON_CAPABILITIES *capabilities)
1134 {
1135 instance->toAddon.addonInstance->GetCapabilities(*capabilities);
1136 }
1137
1138 static inline const char* ADDON_GetDSPName(AddonInstance_AudioDSP const* instance)
1139 {
1140 instance->toAddon.addonInstance->m_dspName = instance->toAddon.addonInstance->GetDSPName();
1141 return instance->toAddon.addonInstance->m_dspName.c_str();
1142 }
1143
1144 static inline const char* ADDON_GetDSPVersion(AddonInstance_AudioDSP const* instance)
1145 {
1146 instance->toAddon.addonInstance->m_dspVersion = instance->toAddon.addonInstance->GetDSPVersion();
1147 return instance->toAddon.addonInstance->m_dspVersion.c_str();
1148 }
1149
1150 static inline AE_DSP_ERROR ADDON_MenuHook(AddonInstance_AudioDSP const* instance, const AE_DSP_MENUHOOK* menuhook, const AE_DSP_MENUHOOK_DATA* item)
1151 {
1152 return instance->toAddon.addonInstance->MenuHook(*menuhook, *item);
1153 }
1154
1155 static inline AE_DSP_ERROR ADDON_StreamCreate(AddonInstance_AudioDSP const* instance, const AE_DSP_SETTINGS *addonSettings, const AE_DSP_STREAM_PROPERTIES* properties, ADDON_HANDLE handle)
1156 {
1157 return instance->toAddon.addonInstance->StreamCreate(*addonSettings, *properties, handle);
1158 }
1159
1160 static inline AE_DSP_ERROR ADDON_StreamDestroy(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1161 {
1162 return instance->toAddon.addonInstance->StreamDestroy(handle);
1163 }
1164
1165 static inline AE_DSP_ERROR ADDON_StreamIsModeSupported(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, AE_DSP_MODE_TYPE type, unsigned int mode_id, int unique_db_mode_id)
1166 {
1167 return instance->toAddon.addonInstance->StreamIsModeSupported(handle, type, mode_id, unique_db_mode_id);
1168 }
1169
1170 static inline AE_DSP_ERROR ADDON_StreamInitialize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, const AE_DSP_SETTINGS *addonSettings)
1171 {
1172 return instance->toAddon.addonInstance->StreamInitialize(handle, *addonSettings);
1173 }
1174
1175 static inline bool ADDON_InputProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, const float** array_in, unsigned int samples)
1176 {
1177 return instance->toAddon.addonInstance->InputProcess(handle, array_in, samples);
1178 }
1179
1180 static inline unsigned int ADDON_InputResampleProcessNeededSamplesize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1181 {
1182 return instance->toAddon.addonInstance->InputResampleProcessNeededSamplesize(handle);
1183 }
1184
1185 static inline unsigned int ADDON_InputResampleProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples)
1186 {
1187 return instance->toAddon.addonInstance->InputResampleProcess(handle, array_in, array_out, samples);
1188 }
1189
1190 static inline int ADDON_InputResampleSampleRate(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1191 {
1192 return instance->toAddon.addonInstance->InputResampleSampleRate(handle);
1193 }
1194
1195 static inline float ADDON_InputResampleGetDelay(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1196 {
1197 return instance->toAddon.addonInstance->InputResampleGetDelay(handle);
1198 }
1199
1200 static inline unsigned int ADDON_PreProcessNeededSamplesize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id)
1201 {
1202 return instance->toAddon.addonInstance->PreProcessNeededSamplesize(handle, mode_id);
1203 }
1204
1205 static inline float ADDON_PreProcessGetDelay(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id)
1206 {
1207 return instance->toAddon.addonInstance->PreProcessGetDelay(handle, mode_id);
1208 }
1209
1210 static inline unsigned int ADDON_PreProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id, const float** array_in, float** array_out, unsigned int samples)
1211 {
1212 return instance->toAddon.addonInstance->PreProcess(handle, mode_id, array_in, array_out, samples);
1213 }
1214
1215 static inline AE_DSP_ERROR ADDON_MasterProcessSetMode(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, AE_DSP_STREAMTYPE type, unsigned int mode_id, int unique_db_mode_id)
1216 {
1217 return instance->toAddon.addonInstance->MasterProcessSetMode(handle, type, mode_id, unique_db_mode_id);
1218 }
1219
1220 static inline unsigned int ADDON_MasterProcessNeededSamplesize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1221 {
1222 return instance->toAddon.addonInstance->MasterProcessNeededSamplesize(handle);
1223 }
1224
1225 static inline float ADDON_MasterProcessGetDelay(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1226 {
1227 return instance->toAddon.addonInstance->MasterProcessGetDelay(handle);
1228 }
1229
1230 static inline int ADDON_MasterProcessGetOutChannels(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned long* out_channel_present_flags)
1231 {
1232 return instance->toAddon.addonInstance->MasterProcessGetOutChannels(handle, *out_channel_present_flags);
1233 }
1234
1235 static inline unsigned int ADDON_MasterProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples)
1236 {
1237 return instance->toAddon.addonInstance->MasterProcess(handle, array_in, array_out, samples);
1238 }
1239
1240 static inline const char* ADDON_MasterProcessGetStreamInfoString(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1241 {
1242 instance->toAddon.addonInstance->m_streamInfoString = instance->toAddon.addonInstance->MasterProcessGetStreamInfoString(handle);
1243 return instance->toAddon.addonInstance->m_streamInfoString.c_str();
1244 }
1245
1246 static inline unsigned int ADDON_PostProcessNeededSamplesize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id)
1247 {
1248 return instance->toAddon.addonInstance->PostProcessNeededSamplesize(handle, mode_id);
1249 }
1250
1251 static inline float ADDON_PostProcessGetDelay(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id)
1252 {
1253 return instance->toAddon.addonInstance->PostProcessGetDelay(handle, mode_id);
1254 }
1255
1256 static inline unsigned int ADDON_PostProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, unsigned int mode_id, const float** array_in, float** array_out, unsigned int samples)
1257 {
1258 return instance->toAddon.addonInstance->PostProcess(handle, mode_id, array_in, array_out, samples);
1259 }
1260
1261 static inline unsigned int ADDON_OutputResampleProcessNeededSamplesize(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1262 {
1263 return instance->toAddon.addonInstance->OutputResampleProcessNeededSamplesize(handle);
1264 }
1265
1266 static inline unsigned int ADDON_OutputResampleProcess(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle, const float** array_in, float** array_out, unsigned int samples)
1267 {
1268 return instance->toAddon.addonInstance->OutputResampleProcess(handle, array_in, array_out, samples);
1269 }
1270
1271 static inline int ADDON_OutputResampleSampleRate(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1272 {
1273 return instance->toAddon.addonInstance->OutputResampleSampleRate(handle);
1274 }
1275
1276 static inline float ADDON_OutputResampleGetDelay(AddonInstance_AudioDSP const* instance, const ADDON_HANDLE handle)
1277 {
1278 return instance->toAddon.addonInstance->OutputResampleGetDelay(handle);
1279 }
1280
1281 std::string m_dspName;
1282 std::string m_dspVersion;
1283 std::string m_streamInfoString;
1284 AddonInstance_AudioDSP* m_instanceData;
1285 };
1286
1287} /* namespace addon */
1288} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h
new file mode 100644
index 0000000..f56f8ae
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioDecoder.h
@@ -0,0 +1,240 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "../AddonBase.h"
23#ifdef BUILD_KODI_ADDON
24#include "../AEChannelData.h"
25#else
26#include "cores/AudioEngine/Utils/AEChannelData.h"
27#endif
28#include <stdint.h>
29
30namespace kodi { namespace addon { class CInstanceAudioDecoder; }}
31
32extern "C"
33{
34
35 typedef struct AddonProps_AudioDecoder
36 {
37 int dummy;
38 } AddonProps_AudioDecoder;
39
40 typedef struct AddonToKodiFuncTable_AudioDecoder
41 {
42 void* kodiInstance;
43 } AddonToKodiFuncTable_AudioDecoder;
44
45 struct AddonInstance_AudioDecoder;
46 typedef struct KodiToAddonFuncTable_AudioDecoder
47 {
48 kodi::addon::CInstanceAudioDecoder* addonInstance;
49 bool (__cdecl* init) (const AddonInstance_AudioDecoder* instance,
50 const char* file, unsigned int filecache,
51 int* channels, int* samplerate,
52 int* bitspersample, int64_t* totaltime,
53 int* bitrate, AEDataFormat* format,
54 const AEChannel** info);
55 int (__cdecl* read_pcm) (const AddonInstance_AudioDecoder* instance, uint8_t* buffer, int size, int* actualsize);
56 int64_t (__cdecl* seek) (const AddonInstance_AudioDecoder* instance, int64_t time);
57 bool (__cdecl* read_tag) (const AddonInstance_AudioDecoder* instance,
58 const char* file, char* title,
59 char* artist, int* length);
60 int (__cdecl* track_count) (const AddonInstance_AudioDecoder* instance, const char* file);
61 } KodiToAddonFuncTable_AudioDecoder;
62
63 typedef struct AddonInstance_AudioDecoder
64 {
65 AddonProps_AudioDecoder props;
66 AddonToKodiFuncTable_AudioDecoder toKodi;
67 KodiToAddonFuncTable_AudioDecoder toAddon;
68 } AddonInstance_AudioDecoder;
69
70} /* extern "C" */
71
72namespace kodi
73{
74namespace addon
75{
76
77 class CInstanceAudioDecoder : public IAddonInstance
78 {
79 public:
80 //==========================================================================
81 /// @brief Class constructor
82 ///
83 /// @param[in] instance The from Kodi given instance given be
84 /// add-on CreateInstance call with instance
85 /// id ADDON_INSTANCE_AUDIODECODER.
86 CInstanceAudioDecoder(KODI_HANDLE instance)
87 : IAddonInstance(ADDON_INSTANCE_AUDIODECODER)
88 {
89 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
90 throw std::logic_error("kodi::addon::CInstanceAudioDecoder: Creation of multiple together with single instance way is not allowed!");
91
92 SetAddonStruct(instance);
93 }
94 //--------------------------------------------------------------------------
95
96 //==========================================================================
97 /// @ingroup cpp_kodi_addon_audiodecoder
98 /// @brief Initialize a decoder
99 ///
100 /// @param[in] filename The file to read
101 /// @param[in] filecache The file cache size
102 /// @param[out] channels Number of channels in output stream
103 /// @param[out] samplerate Samplerate of output stream
104 /// @param[out] bitspersample Bits per sample in output stream
105 /// @param[out] totaltime Total time for stream
106 /// @param[out] bitrate Average bitrate of input stream
107 /// @param[out] format Data format for output stream
108 /// @param[out] channellist Channel mapping for output stream
109 /// @return true if successfully done, otherwise
110 /// false
111 ///
112 virtual bool Init(const std::string& filename, unsigned int filecache,
113 int& channels, int& samplerate,
114 int& bitspersample, int64_t& totaltime,
115 int& bitrate, AEDataFormat& format,
116 std::vector<AEChannel>& channellist) = 0;
117 //--------------------------------------------------------------------------
118
119 //==========================================================================
120 /// @ingroup cpp_kodi_addon_audiodecoder
121 /// @brief Produce some noise
122 ///
123 /// @param[in] buffer Output buffer
124 /// @param[in] size Size of output buffer
125 /// @param[out] actualsize Actual number of bytes written to output buffer
126 /// @return Return with following possible values:
127 /// | Value | Description |
128 /// |:-----:|:-----------------------------|
129 /// | 0 | on success
130 /// | -1 | on end of stream
131 /// | 1 | on failure
132 ///
133 virtual int ReadPCM(uint8_t* buffer, int size, int& actualsize) = 0;
134 //--------------------------------------------------------------------------
135
136 //==========================================================================
137 /// @ingroup cpp_kodi_addon_audiodecoder
138 /// @brief Seek in output stream
139 ///
140 /// @param[in] time Time position to seek to in milliseconds
141 /// @return Time position seek ended up on
142 ///
143 virtual int64_t Seek(int64_t time) { return time; }
144 //--------------------------------------------------------------------------
145
146 //==========================================================================
147 /// @ingroup cpp_kodi_addon_audiodecoder
148 /// @brief Read tag of a file
149 ///
150 /// @param[in] file File to read tag for
151 /// @param[out] title Title of file
152 /// @param[out] artist Artist of file
153 /// @param[out] length Length of file
154 /// @return True on success, false on failure
155 ///
156 virtual bool ReadTag(const std::string& file, std::string& title, std::string& artist, int& length) { return false; }
157 //--------------------------------------------------------------------------
158
159 //==========================================================================
160 /// @ingroup cpp_kodi_addon_audiodecoder
161 /// @brief Get number of tracks in a file
162 ///
163 /// @param[in] file File to read tag for
164 /// @return Number of tracks in file
165 ///
166 virtual int TrackCount(const std::string& file) { return 1; }
167 //--------------------------------------------------------------------------
168
169 private:
170 void SetAddonStruct(KODI_HANDLE instance)
171 {
172 if (instance == nullptr)
173 throw std::logic_error("kodi::addon::CInstanceAudioDecoder: Creation with empty addon structure not allowed, table must be given from Kodi!");
174
175 m_instanceData = static_cast<AddonInstance_AudioDecoder*>(instance);
176
177 m_instanceData->toAddon.addonInstance = this;
178 m_instanceData->toAddon.init = ADDON_Init;
179 m_instanceData->toAddon.read_pcm = ADDON_ReadPCM;
180 m_instanceData->toAddon.seek = ADDON_Seek;
181 m_instanceData->toAddon.read_tag = ADDON_ReadTag;
182 m_instanceData->toAddon.track_count = ADDON_TrackCount;
183 }
184
185 inline static bool ADDON_Init(const AddonInstance_AudioDecoder* instance, const char* file, unsigned int filecache,
186 int* channels, int* samplerate,
187 int* bitspersample, int64_t* totaltime,
188 int* bitrate, AEDataFormat* format,
189 const AEChannel** info)
190 {
191 instance->toAddon.addonInstance->m_channelList.clear();
192 bool ret = instance->toAddon.addonInstance->Init(file, filecache, *channels,
193 *samplerate, *bitspersample,
194 *totaltime, *bitrate, *format,
195 instance->toAddon.addonInstance->m_channelList);
196 if (!instance->toAddon.addonInstance->m_channelList.empty())
197 {
198 if (instance->toAddon.addonInstance->m_channelList.back() != AE_CH_NULL)
199 instance->toAddon.addonInstance->m_channelList.push_back(AE_CH_NULL);
200 *info = instance->toAddon.addonInstance->m_channelList.data();
201 }
202 else
203 *info = nullptr;
204 return ret;
205 }
206
207 inline static int ADDON_ReadPCM(const AddonInstance_AudioDecoder* instance, uint8_t* buffer, int size, int* actualsize)
208 {
209 return instance->toAddon.addonInstance->ReadPCM(buffer, size, *actualsize);
210 }
211
212 inline static int64_t ADDON_Seek(const AddonInstance_AudioDecoder* instance, int64_t time)
213 {
214 return instance->toAddon.addonInstance->Seek(time);
215 }
216
217 inline static bool ADDON_ReadTag(const AddonInstance_AudioDecoder* instance, const char* file, char* title, char* artist, int* length)
218 {
219 std::string intTitle;
220 std::string intArtist;
221 bool ret = instance->toAddon.addonInstance->ReadTag(file, intTitle, intArtist, *length);
222 if (ret)
223 {
224 strncpy(title, intTitle.c_str(), ADDON_STANDARD_STRING_LENGTH_SMALL-1);
225 strncpy(artist, intArtist.c_str(), ADDON_STANDARD_STRING_LENGTH_SMALL-1);
226 }
227 return ret;
228 }
229
230 inline static int ADDON_TrackCount(const AddonInstance_AudioDecoder* instance, const char* file)
231 {
232 return instance->toAddon.addonInstance->TrackCount(file);
233 }
234
235 std::vector<AEChannel> m_channelList;
236 AddonInstance_AudioDecoder* m_instanceData;
237 };
238
239} /* namespace addon */
240} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h
new file mode 100644
index 0000000..3d59a99
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/AudioEncoder.h
@@ -0,0 +1,223 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "../AddonBase.h"
23
24namespace kodi { namespace addon { class CInstanceAudioEncoder; }}
25
26extern "C"
27{
28
29 typedef struct AddonProps_AudioEncoder
30 {
31 int dummy;
32 } AddonProps_AudioEncoder;
33
34 typedef struct AddonToKodiFuncTable_AudioEncoder
35 {
36 void* kodiInstance;
37 int (*write) (void* kodiInstance, const uint8_t* data, int len);
38 int64_t (*seek)(void* kodiInstance, int64_t pos, int whence);
39 } AddonToKodiFuncTable_AudioEncoder;
40
41 struct AddonInstance_AudioEncoder;
42 typedef struct KodiToAddonFuncTable_AudioEncoder
43 {
44 kodi::addon::CInstanceAudioEncoder* addonInstance;
45 bool (__cdecl* start) (const AddonInstance_AudioEncoder* instance, int in_channels, int in_rate, int in_bits,
46 const char* title, const char* artist,
47 const char* albumartist, const char* album,
48 const char* year, const char* track,
49 const char* genre, const char* comment,
50 int track_length);
51 int (__cdecl* encode) (const AddonInstance_AudioEncoder* instance, int num_bytes_read, const uint8_t* pbt_stream);
52 bool (__cdecl* finish) (const AddonInstance_AudioEncoder* instance);
53 } KodiToAddonFuncTable_AudioEncoder;
54
55 typedef struct AddonInstance_AudioEncoder
56 {
57 AddonProps_AudioEncoder props;
58 AddonToKodiFuncTable_AudioEncoder toKodi;
59 KodiToAddonFuncTable_AudioEncoder toAddon;
60 } AddonInstance_AudioEncoder;
61
62} /* extern "C" */
63
64namespace kodi
65{
66namespace addon
67{
68
69 class CInstanceAudioEncoder : public IAddonInstance
70 {
71 public:
72 //==========================================================================
73 /// @brief Class constructor
74 ///
75 /// @param[in] instance The from Kodi given instance given be
76 /// add-on CreateInstance call with instance
77 /// id ADDON_INSTANCE_AUDIOENCODER.
78 CInstanceAudioEncoder(KODI_HANDLE instance)
79 : IAddonInstance(ADDON_INSTANCE_AUDIOENCODER)
80 {
81 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
82 throw std::logic_error("kodi::addon::CInstanceAudioEncoder: Creation of multiple together with single instance way is not allowed!");
83
84 SetAddonStruct(instance);
85 }
86 //--------------------------------------------------------------------------
87
88 //==========================================================================
89 /// \brief Start encoder (**required**)
90 ///
91 /// \param[in] inChannels Number of channels
92 /// \param[in] inRate Sample rate of input data
93 /// \param[in] inBits Bits per sample in input data
94 /// \param[in] title The title of the song
95 /// \param[in] artist The artist of the song
96 /// \param[in] albumartist The albumartist of the song
97 /// \param[in] year The year of the song
98 /// \param[in] track The track number of the song
99 /// \param[in] genre The genre of the song
100 /// \param[in] comment A comment to attach to the song
101 /// \param[in] trackLength Total track length in seconds
102 /// \return True on success, false on failure.
103 ///
104 virtual bool Start(int inChannels,
105 int inRate,
106 int inBits,
107 const std::string& title,
108 const std::string& artist,
109 const std::string& albumartist,
110 const std::string& album,
111 const std::string& year,
112 const std::string& track,
113 const std::string& genre,
114 const std::string& comment,
115 int trackLength) = 0;
116 //--------------------------------------------------------------------------
117
118 //==========================================================================
119 /// \brief Encode a chunk of audio (**required**)
120 ///
121 /// \param[in] numBytesRead Number of bytes in input buffer
122 /// \param[in] pbtStream the input buffer
123 /// \return Number of bytes consumed
124 ///
125 virtual int Encode(int numBytesRead, const uint8_t* pbtStream) = 0;
126 //--------------------------------------------------------------------------
127
128 //==========================================================================
129 /// \brief Finalize encoding (**optional**)
130 ///
131 /// \return True on success, false on failure.
132 ///
133 virtual bool Finish() { return true; }
134 //--------------------------------------------------------------------------
135
136 //==========================================================================
137 /// \brief Write block of data
138 ///
139 /// \param[in] data Pointer to the array of elements to be
140 /// written
141 /// \param[in] length Size in bytes to be written.
142 /// \return The total number of bytes
143 /// successfully written is returned.
144 int Write(const uint8_t* data, int length)
145 {
146 return m_instanceData->toKodi.write(m_instanceData->toKodi.kodiInstance, data, length);
147 }
148 //--------------------------------------------------------------------------
149
150 //==========================================================================
151 /// \brief Set the file's current position.
152 ///
153 /// The whence argument is optional and defaults to SEEK_SET (0)
154 ///
155 /// \param[in] position the position that you want to seek to
156 /// \param[in] whence [optional] offset relative to
157 /// You can set the value of whence to one
158 /// of three things:
159 /// | Value | int | Description |
160 /// |:--------:|:---:|:---------------------------------------------------|
161 /// | 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.
162 /// | 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."
163 /// | 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.
164 ///
165 /// \return Returns the resulting offset location as
166 /// measured in bytes from the beginning of
167 /// the file. On error, the value -1 is
168 /// returned.
169 int64_t Seek(int64_t position, int whence = SEEK_SET)
170 {
171 return m_instanceData->toKodi.seek(m_instanceData->toKodi.kodiInstance, position, whence);
172 }
173 //--------------------------------------------------------------------------
174
175 private:
176 void SetAddonStruct(KODI_HANDLE instance)
177 {
178 if (instance == nullptr)
179 throw std::logic_error("kodi::addon::CInstanceAudioEncoder: Creation with empty addon structure not allowed, table must be given from Kodi!");
180
181 m_instanceData = static_cast<AddonInstance_AudioEncoder*>(instance);
182 m_instanceData->toAddon.addonInstance = this;
183 m_instanceData->toAddon.start = ADDON_Start;
184 m_instanceData->toAddon.encode = ADDON_Encode;
185 m_instanceData->toAddon.finish = ADDON_Finish;
186 }
187
188 inline static bool ADDON_Start(const AddonInstance_AudioEncoder* instance, int inChannels, int inRate, int inBits,
189 const char* title, const char* artist,
190 const char* albumartist, const char* album,
191 const char* year, const char* track,
192 const char* genre, const char* comment,
193 int trackLength)
194 {
195 return instance->toAddon.addonInstance->Start(inChannels,
196 inRate,
197 inBits,
198 title,
199 artist,
200 albumartist,
201 album,
202 year,
203 track,
204 genre,
205 comment,
206 trackLength);
207 }
208
209 inline static int ADDON_Encode(const AddonInstance_AudioEncoder* instance, int numBytesRead, const uint8_t* pbtStream)
210 {
211 return instance->toAddon.addonInstance->Encode(numBytesRead, pbtStream);
212 }
213
214 inline static bool ADDON_Finish(const AddonInstance_AudioEncoder* instance)
215 {
216 return instance->toAddon.addonInstance->Finish();
217 }
218
219 AddonInstance_AudioEncoder* m_instanceData;
220 };
221
222} /* namespace addon */
223} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h
new file mode 100644
index 0000000..a854711
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/ImageDecoder.h
@@ -0,0 +1,163 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "../AddonBase.h"
23
24namespace kodi { namespace addon { class CInstanceImageDecoder; }}
25
26extern "C"
27{
28
29 typedef struct AddonProps_ImageDecoder
30 {
31 const char* mimetype;
32 } AddonProps_ImageDecoder;
33
34 typedef struct AddonToKodiFuncTable_ImageDecoder
35 {
36 KODI_HANDLE kodi_instance;
37 } AddonToKodiFuncTable_ImageDecoder;
38
39 struct AddonInstance_ImageDecoder;
40 typedef struct KodiToAddonFuncTable_ImageDecoder
41 {
42 kodi::addon::CInstanceImageDecoder* addonInstance;
43 bool (__cdecl* load_image_from_memory) (const AddonInstance_ImageDecoder* instance,
44 unsigned char* buffer, unsigned int buf_size,
45 unsigned int* width, unsigned int* height);
46
47 bool (__cdecl* decode) (const AddonInstance_ImageDecoder* instance,
48 unsigned char* pixels,
49 unsigned int width, unsigned int height,
50 unsigned int pitch, unsigned int format);
51 } KodiToAddonFuncTable_ImageDecoder;
52
53 typedef struct AddonInstance_ImageDecoder
54 {
55 AddonProps_ImageDecoder props;
56 AddonToKodiFuncTable_ImageDecoder toKodi;
57 KodiToAddonFuncTable_ImageDecoder toAddon;
58 } AddonInstance_ImageDecoder;
59
60} /* extern "C" */
61
62typedef enum ImageFormat : unsigned int
63{
64 ADDON_IMG_FMT_A8R8G8B8 = 1,
65 ADDON_IMG_FMT_A8 = 2,
66 ADDON_IMG_FMT_RGBA8 = 3,
67 ADDON_IMG_FMT_RGB8 = 4
68} ImageFormat;
69
70namespace kodi
71{
72namespace addon
73{
74
75 class CInstanceImageDecoder : public IAddonInstance
76 {
77 public:
78 //==========================================================================
79 /// @brief Class constructor
80 ///
81 /// @param[in] instance The from Kodi given instance given be
82 /// add-on CreateInstance call with instance
83 /// id ADDON_INSTANCE_IMAGEDECODER.
84 CInstanceImageDecoder(KODI_HANDLE instance)
85 : IAddonInstance(ADDON_INSTANCE_IMAGEDECODER)
86 {
87 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
88 throw std::logic_error("kodi::addon::CInstanceImageDecoder: Creation of multiple together with single instance way is not allowed!");
89
90 SetAddonStruct(instance);
91 }
92 //--------------------------------------------------------------------------
93
94 ~CInstanceImageDecoder() override = default;
95
96 //==========================================================================
97 /// @brief Initialize an encoder
98 ///
99 /// @param[in] buffer The data to read from memory
100 /// @param[in] bufSize The buffer size
101 /// @param[in,out] width The optimal width of image on entry, obtained width on return
102 /// @param[in,out] height The optimal height of image, actual obtained height on return
103 /// @return true if successful done, false on error
104 ///
105 virtual bool LoadImageFromMemory(unsigned char* buffer, unsigned int bufSize,
106 unsigned int& width, unsigned int& height) = 0;
107 //--------------------------------------------------------------------------
108
109 //==========================================================================
110 /// @brief Decode previously loaded image
111 ///
112 /// @param[in] pixels Output buffer
113 /// @param[in] width Width of output image
114 /// @param[in] height Height of output image
115 /// @param[in] pitch Pitch of output image
116 /// @param[in] format Format of output image
117 /// @return true if successful done, false on error
118 ///
119 virtual bool Decode(unsigned char* pixels,
120 unsigned int width, unsigned int height,
121 unsigned int pitch, ImageFormat format) = 0;
122 //--------------------------------------------------------------------------
123
124 //==========================================================================
125 /// @brief Get the wanted mime type from Kodi
126 ///
127 /// @return the mimetype wanted from Kodi
128 ///
129 inline std::string MimeType() { return m_instanceData->props.mimetype; }
130 //--------------------------------------------------------------------------
131
132 private:
133 void SetAddonStruct(KODI_HANDLE instance)
134 {
135 if (instance == nullptr)
136 throw std::logic_error("kodi::addon::CInstanceImageDecoder: Creation with empty addon structure not allowed, table must be given from Kodi!");
137
138 m_instanceData = static_cast<AddonInstance_ImageDecoder*>(instance);
139 m_instanceData->toAddon.addonInstance = this;
140 m_instanceData->toAddon.load_image_from_memory = ADDON_LoadImageFromMemory;
141 m_instanceData->toAddon.decode = ADDON_Decode;
142 }
143
144 inline static bool ADDON_LoadImageFromMemory(const AddonInstance_ImageDecoder* instance,
145 unsigned char* buffer, unsigned int bufSize,
146 unsigned int* width, unsigned int* height)
147 {
148 return instance->toAddon.addonInstance->LoadImageFromMemory(buffer, bufSize, *width, *height);
149 }
150
151 inline static bool ADDON_Decode(const AddonInstance_ImageDecoder* instance,
152 unsigned char* pixels,
153 unsigned int width, unsigned int height,
154 unsigned int pitch, unsigned int format)
155 {
156 return instance->toAddon.addonInstance->Decode(pixels, width, height, pitch, static_cast<ImageFormat>(format));
157 }
158
159 AddonInstance_ImageDecoder* m_instanceData;
160 };
161
162} /* namespace addon */
163} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
new file mode 100644
index 0000000..76cfe92
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Inputstream.h
@@ -0,0 +1,621 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22/*
23 * Parts with a comment named "internal" are only used inside header and not
24 * used or accessed direct during add-on development!
25 */
26
27#include "../AddonBase.h"
28#include "../StreamCrypto.h"
29#include "../StreamCodec.h"
30
31#ifdef BUILD_KODI_ADDON
32#include "../DVDDemuxPacket.h"
33#else
34#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
35#endif
36
37namespace kodi { namespace addon { class CInstanceInputStream; }}
38
39extern "C" {
40
41 /*!
42 * @brief InputStream add-on capabilities. All capabilities are set to "false" as default.
43 */
44 typedef struct INPUTSTREAM_CAPABILITIES
45 {
46 enum MASKTYPE: uint32_t
47 {
48 /// supports interface IDemux
49 SUPPORTS_IDEMUX = (1 << 0),
50
51 /// supports interface IPosTime
52 SUPPORTS_IPOSTIME = (1 << 1),
53
54 /// supports interface IDisplayTime
55 SUPPORTS_IDISPLAYTIME = (1 << 2),
56
57 /// supports seek
58 SUPPORTS_SEEK = (1 << 3),
59
60 /// supports pause
61 SUPPORTS_PAUSE = (1 << 4)
62 };
63
64 /// set of supported capabilities
65 uint32_t m_mask;
66 } INPUTSTREAM_CAPABILITIES;
67
68 /*!
69 * @brief structure of key/value pairs passed to addon on Open()
70 */
71 typedef struct INPUTSTREAM
72 {
73 static const unsigned int MAX_INFO_COUNT = 8;
74
75 const char *m_strURL;
76
77 unsigned int m_nCountInfoValues;
78 struct LISTITEMPROPERTY
79 {
80 const char *m_strKey;
81 const char *m_strValue;
82 } m_ListItemProperties[MAX_INFO_COUNT];
83
84 const char *m_libFolder;
85 const char *m_profileFolder;
86 } INPUTSTREAM;
87
88 /*!
89 * @brief Array of stream IDs
90 */
91 typedef struct INPUTSTREAM_IDS
92 {
93 static const unsigned int MAX_STREAM_COUNT = 32;
94 unsigned int m_streamCount;
95 unsigned int m_streamIds[MAX_STREAM_COUNT];
96 } INPUTSTREAM_IDS;
97
98 /*!
99 * @brief stream properties
100 */
101 typedef struct INPUTSTREAM_INFO
102 {
103 enum STREAM_TYPE
104 {
105 TYPE_NONE,
106 TYPE_VIDEO,
107 TYPE_AUDIO,
108 TYPE_SUBTITLE,
109 TYPE_TELETEXT
110 } m_streamType;
111
112 enum Codec_FEATURES
113 {
114 FEATURE_DECODE = 1
115 };
116 unsigned int m_features;
117
118 char m_codecName[32]; /*!< @brief (required) name of codec according to ffmpeg */
119 char m_codecInternalName[32]; /*!< @brief (optional) internal name of codec (selectionstream info) */
120 STREAMCODEC_PROFILE m_codecProfile; /*!< @brief (optional) the profile of the codec */
121 unsigned int m_pID; /*!< @brief (required) physical index */
122
123 const uint8_t *m_ExtraData;
124 unsigned int m_ExtraSize;
125
126 char m_language[4]; /*!< @brief ISO 639 3-letter language code (empty string if undefined) */
127
128 unsigned int m_FpsScale; /*!< @brief Scale of 1000 and a rate of 29970 will result in 29.97 fps */
129 unsigned int m_FpsRate;
130 unsigned int m_Height; /*!< @brief height of the stream reported by the demuxer */
131 unsigned int m_Width; /*!< @brief width of the stream reported by the demuxer */
132 float m_Aspect; /*!< @brief display aspect of stream */
133
134 unsigned int m_Channels; /*!< @brief (required) amount of channels */
135 unsigned int m_SampleRate; /*!< @brief (required) sample rate */
136 unsigned int m_BitRate; /*!< @brief (required) bit rate */
137 unsigned int m_BitsPerSample; /*!< @brief (required) bits per sample */
138 unsigned int m_BlockAlign;
139
140 CRYPTO_INFO m_cryptoInfo;
141 } INPUTSTREAM_INFO;
142
143 /*!
144 * @brief Structure to transfer the methods from xbmc_inputstream_dll.h to XBMC
145 */
146
147 // this are properties given to the addon on create
148 // at this time we have no parameters for the addon
149 typedef struct AddonProps_InputStream /* internal */
150 {
151 int dummy;
152 } AddonProps_InputStream;
153
154 typedef struct AddonToKodiFuncTable_InputStream /* internal */
155 {
156 KODI_HANDLE kodiInstance;
157 DemuxPacket* (*allocate_demux_packet)(void* kodiInstance, int data_size);
158 DemuxPacket* (*allocate_encrypted_demux_packet)(void* kodiInstance, unsigned int data_size, unsigned int encrypted_subsample_count);
159 void (*free_demux_packet)(void* kodiInstance, DemuxPacket* packet);
160 } AddonToKodiFuncTable_InputStream;
161
162 struct AddonInstance_InputStream;
163 typedef struct KodiToAddonFuncTable_InputStream /* internal */
164 {
165 kodi::addon::CInstanceInputStream* addonInstance;
166
167 bool (__cdecl* open)(const AddonInstance_InputStream* instance, INPUTSTREAM* props);
168 void (__cdecl* close)(const AddonInstance_InputStream* instance);
169 const char* (__cdecl* get_path_list)(const AddonInstance_InputStream* instance);
170 void (__cdecl* get_capabilities)(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities);
171
172 // IDemux
173 struct INPUTSTREAM_IDS (__cdecl* get_stream_ids)(const AddonInstance_InputStream* instance);
174 struct INPUTSTREAM_INFO (__cdecl* get_stream)(const AddonInstance_InputStream* instance, int streamid);
175 void (__cdecl* enable_stream)(const AddonInstance_InputStream* instance, int streamid, bool enable);
176 void(__cdecl* open_stream)(const AddonInstance_InputStream* instance, int streamid);
177 void (__cdecl* demux_reset)(const AddonInstance_InputStream* instance);
178 void (__cdecl* demux_abort)(const AddonInstance_InputStream* instance);
179 void (__cdecl* demux_flush)(const AddonInstance_InputStream* instance);
180 DemuxPacket* (__cdecl* demux_read)(const AddonInstance_InputStream* instance);
181 bool (__cdecl* demux_seek_time)(const AddonInstance_InputStream* instance, double time, bool backwards, double* startpts);
182 void (__cdecl* demux_set_speed)(const AddonInstance_InputStream* instance, int speed);
183 void (__cdecl* set_video_resolution)(const AddonInstance_InputStream* instance, int width, int height);
184
185 // IDisplayTime
186 int (__cdecl* get_total_time)(const AddonInstance_InputStream* instance);
187 int (__cdecl* get_time)(const AddonInstance_InputStream* instance);
188
189 // IPosTime
190 bool (__cdecl* pos_time)(const AddonInstance_InputStream* instance, int ms);
191
192 // Seekable (mandatory)
193 bool (__cdecl* can_pause_stream)(const AddonInstance_InputStream* instance);
194 bool (__cdecl* can_seek_stream)(const AddonInstance_InputStream* instance);
195
196 int (__cdecl* read_stream)(const AddonInstance_InputStream* instance, uint8_t* buffer, unsigned int bufferSize);
197 int64_t(__cdecl* seek_stream)(const AddonInstance_InputStream* instance, int64_t position, int whence);
198 int64_t (__cdecl* position_stream)(const AddonInstance_InputStream* instance);
199 int64_t (__cdecl* length_stream)(const AddonInstance_InputStream* instance);
200 void (__cdecl* pause_stream)(const AddonInstance_InputStream* instance, double time);
201 bool (__cdecl* is_real_time_stream)(const AddonInstance_InputStream* instance);
202 } KodiToAddonFuncTable_InputStream;
203
204 typedef struct AddonInstance_InputStream /* internal */
205 {
206 AddonProps_InputStream props;
207 AddonToKodiFuncTable_InputStream toKodi;
208 KodiToAddonFuncTable_InputStream toAddon;
209 } AddonInstance_InputStream;
210
211} /* extern "C" */
212
213namespace kodi
214{
215namespace addon
216{
217
218 class CInstanceInputStream : public IAddonInstance
219 {
220 public:
221 CInstanceInputStream(KODI_HANDLE instance)
222 : IAddonInstance(ADDON_INSTANCE_INPUTSTREAM)
223 {
224 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
225 throw std::logic_error("kodi::addon::CInstanceInputStream: Creation of multiple together with single instance way is not allowed!");
226
227 SetAddonStruct(instance);
228 }
229
230 ~CInstanceInputStream() override = default;
231
232 /*!
233 * Open a stream.
234 * @param props
235 * @return True if the stream has been opened successfully, false otherwise.
236 * @remarks
237 */
238 virtual bool Open(INPUTSTREAM& props) = 0;
239
240 /*!
241 * Close an open stream.
242 * @remarks
243 */
244 virtual void Close() = 0;
245
246 /*!
247 * Get Capabilities of this addon.
248 * @param capabilities The add-on's capabilities.
249 * @remarks
250 */
251 virtual void GetCapabilities(INPUTSTREAM_CAPABILITIES& capabilities) = 0;
252
253 /*!
254 * Get IDs of available streams
255 * @remarks
256 */
257 virtual INPUTSTREAM_IDS GetStreamIds() = 0;
258
259 /*!
260 * Get stream properties of a stream.
261 * @param streamid unique id of stream
262 * @return struc of stream properties
263 * @remarks
264 */
265 virtual INPUTSTREAM_INFO GetStream(int streamid) = 0;
266
267 /*!
268 * Enable or disable a stream.
269 * A disabled stream does not send demux packets
270 * @param streamid unique id of stream
271 * @param enable true for enable, false for disable
272 * @remarks
273 */
274 virtual void EnableStream(int streamid, bool enable) = 0;
275
276 /*!
277 * Opens a stream for playback.
278 * @param streamid unique id of stream
279 * @remarks
280 */
281 virtual void OpenStream(int streamid) = 0;
282
283 /*!
284 * Reset the demultiplexer in the add-on.
285 * @remarks Required if bHandlesDemuxing is set to true.
286 */
287 virtual void DemuxReset() { }
288
289 /*!
290 * Abort the demultiplexer thread in the add-on.
291 * @remarks Required if bHandlesDemuxing is set to true.
292 */
293 virtual void DemuxAbort() { }
294
295 /*!
296 * Flush all data that's currently in the demultiplexer buffer in the add-on.
297 * @remarks Required if bHandlesDemuxing is set to true.
298 */
299 virtual void DemuxFlush() { }
300
301 /*!
302 * Read the next packet from the demultiplexer, if there is one.
303 * @return The next packet.
304 * If there is no next packet, then the add-on should return the
305 * packet created by calling AllocateDemuxPacket(0) on the callback.
306 * If the stream changed and Kodi's player needs to be reinitialised,
307 * then, the add-on should call AllocateDemuxPacket(0) on the
308 * callback, and set the streamid to DMX_SPECIALID_STREAMCHANGE and
309 * return the value.
310 * The add-on should return NULL if an error occured.
311 * @remarks Return NULL if this add-on won't provide this function.
312 */
313 virtual DemuxPacket* DemuxRead() { return nullptr; }
314
315 /*!
316 * Notify the InputStream addon/demuxer that Kodi wishes to seek the stream by time
317 * Demuxer is required to set stream to an IDR frame
318 * @param time The absolute time since stream start
319 * @param backwards True to seek to keyframe BEFORE time, else AFTER
320 * @param startpts can be updated to point to where display should start
321 * @return True if the seek operation was possible
322 * @remarks Optional, and only used if addon has its own demuxer.
323 */
324 virtual bool DemuxSeekTime(double time, bool backwards, double &startpts) { return false; }
325
326 /*!
327 * Notify the InputStream addon/demuxer that Kodi wishes to change playback speed
328 * @param speed The requested playback speed
329 * @remarks Optional, and only used if addon has its own demuxer.
330 */
331 virtual void DemuxSetSpeed(int speed) { }
332
333 /*!
334 * Sets desired width / height
335 * @param width / hight
336 */
337 virtual void SetVideoResolution(int width, int height) { }
338
339 /*!
340 * Totel time in ms
341 * @remarks
342 */
343 virtual int GetTotalTime() { return -1; }
344
345 /*!
346 * Playing time in ms
347 * @remarks
348 */
349 virtual int GetTime() { return -1; }
350
351 /*!
352 * Positions inputstream to playing time given in ms
353 * @remarks
354 */
355 virtual bool PosTime(int ms) { return false; }
356
357
358 /*!
359 * Check if the backend support pausing the currently playing stream
360 * This will enable/disable the pause button in Kodi based on the return value
361 * @return false if the InputStream addon/backend does not support pausing, true if possible
362 */
363 virtual bool CanPauseStream() { return false; }
364
365 /*!
366 * Check if the backend supports seeking for the currently playing stream
367 * This will enable/disable the rewind/forward buttons in Kodi based on the return value
368 * @return false if the InputStream addon/backend does not support seeking, true if possible
369 */
370 virtual bool CanSeekStream() { return false; }
371
372 /*!
373 * Read from an open stream.
374 * @param buffer The buffer to store the data in.
375 * @param bufferSize The amount of bytes to read.
376 * @return The amount of bytes that were actually read from the stream.
377 * @remarks Return -1 if this add-on won't provide this function.
378 */
379 virtual int ReadStream(uint8_t* buffer, unsigned int bufferSize) { return -1; }
380
381 /*!
382 * Seek in a stream.
383 * @param position The position to seek to.
384 * @param whence ?
385 * @return The new position.
386 * @remarks Return -1 if this add-on won't provide this function.
387 */
388 virtual int64_t SeekStream(int64_t position, int whence = SEEK_SET) { return -1; }
389
390 /*!
391 * @return The position in the stream that's currently being read.
392 * @remarks Return -1 if this add-on won't provide this function.
393 */
394 virtual int64_t PositionStream() { return -1; }
395
396 /*!
397 * @return The total length of the stream that's currently being read.
398 * @remarks Return -1 if this add-on won't provide this function.
399 */
400 virtual int64_t LengthStream() { return -1; }
401
402
403 /*!
404 * @brief Notify the InputStream addon that Kodi (un)paused the currently playing stream
405 */
406 virtual void PauseStream(double time) { }
407
408
409 /*!
410 * Check for real-time streaming
411 * @return true if current stream is real-time
412 */
413 virtual bool IsRealTimeStream() { return true; }
414
415 /*!
416 * @brief Allocate a demux packet. Free with FreeDemuxPacket
417 * @param dataSize The size of the data that will go into the packet
418 * @return The allocated packet
419 */
420 DemuxPacket* AllocateDemuxPacket(int dataSize)
421 {
422 return m_instanceData->toKodi.allocate_demux_packet(m_instanceData->toKodi.kodiInstance, dataSize);
423 }
424
425 /*!
426 * @brief Allocate a demux packet. Free with FreeDemuxPacket
427 * @param dataSize The size of the data that will go into the packet
428 * @return The allocated packet
429 */
430 DemuxPacket* AllocateEncryptedDemuxPacket(int dataSize, unsigned int encryptedSubsampleCount)
431 {
432 return m_instanceData->toKodi.allocate_encrypted_demux_packet(m_instanceData->toKodi.kodiInstance, dataSize, encryptedSubsampleCount);
433 }
434
435 /*!
436 * @brief Free a packet that was allocated with AllocateDemuxPacket
437 * @param packet The packet to free
438 */
439 void FreeDemuxPacket(DemuxPacket* packet)
440 {
441 return m_instanceData->toKodi.free_demux_packet(m_instanceData->toKodi.kodiInstance, packet);
442 }
443
444 private:
445 void SetAddonStruct(KODI_HANDLE instance)
446 {
447 if (instance == nullptr)
448 throw std::logic_error("kodi::addon::CInstanceInputStream: Creation with empty addon structure not allowed, table must be given from Kodi!");
449
450 m_instanceData = static_cast<AddonInstance_InputStream*>(instance);
451 m_instanceData->toAddon.addonInstance = this;
452 m_instanceData->toAddon.open = ADDON_Open;
453 m_instanceData->toAddon.close = ADDON_Close;
454 m_instanceData->toAddon.get_capabilities = ADDON_GetCapabilities;
455
456 m_instanceData->toAddon.get_stream_ids = ADDON_GetStreamIds;
457 m_instanceData->toAddon.get_stream = ADDON_GetStream;
458 m_instanceData->toAddon.enable_stream = ADDON_EnableStream;
459 m_instanceData->toAddon.open_stream = ADDON_OpenStream;
460 m_instanceData->toAddon.demux_reset = ADDON_DemuxReset;
461 m_instanceData->toAddon.demux_abort = ADDON_DemuxAbort;
462 m_instanceData->toAddon.demux_flush = ADDON_DemuxFlush;
463 m_instanceData->toAddon.demux_read = ADDON_DemuxRead;
464 m_instanceData->toAddon.demux_seek_time = ADDON_DemuxSeekTime;
465 m_instanceData->toAddon.demux_set_speed = ADDON_DemuxSetSpeed;
466 m_instanceData->toAddon.set_video_resolution = ADDON_SetVideoResolution;
467
468 m_instanceData->toAddon.get_total_time = ADDON_GetTotalTime;
469 m_instanceData->toAddon.get_time = ADDON_GetTime;
470
471 m_instanceData->toAddon.pos_time = ADDON_PosTime;
472
473 m_instanceData->toAddon.can_pause_stream = ADDON_CanPauseStream;
474 m_instanceData->toAddon.can_seek_stream = ADDON_CanSeekStream;
475
476 m_instanceData->toAddon.read_stream = ADDON_ReadStream;
477 m_instanceData->toAddon.seek_stream = ADDON_SeekStream;
478 m_instanceData->toAddon.position_stream = ADDON_PositionStream;
479 m_instanceData->toAddon.length_stream = ADDON_LengthStream;
480 m_instanceData->toAddon.pause_stream = ADDON_PauseStream;
481 m_instanceData->toAddon.is_real_time_stream = ADDON_IsRealTimeStream;
482 }
483
484 inline static bool ADDON_Open(const AddonInstance_InputStream* instance, INPUTSTREAM* props)
485 {
486 return instance->toAddon.addonInstance->Open(*props);
487 }
488
489 inline static void ADDON_Close(const AddonInstance_InputStream* instance)
490 {
491 instance->toAddon.addonInstance->Close();
492 }
493
494 inline static void ADDON_GetCapabilities(const AddonInstance_InputStream* instance, INPUTSTREAM_CAPABILITIES* capabilities)
495 {
496 instance->toAddon.addonInstance->GetCapabilities(*capabilities);
497 }
498
499
500 // IDemux
501 inline static struct INPUTSTREAM_IDS ADDON_GetStreamIds(const AddonInstance_InputStream* instance)
502 {
503 return instance->toAddon.addonInstance->GetStreamIds();
504 }
505
506 inline static struct INPUTSTREAM_INFO ADDON_GetStream(const AddonInstance_InputStream* instance, int streamid)
507 {
508 return instance->toAddon.addonInstance->GetStream(streamid);
509 }
510
511 inline static void ADDON_EnableStream(const AddonInstance_InputStream* instance, int streamid, bool enable)
512 {
513 instance->toAddon.addonInstance->EnableStream(streamid, enable);
514 }
515
516 inline static void ADDON_OpenStream(const AddonInstance_InputStream* instance, int streamid)
517 {
518 instance->toAddon.addonInstance->OpenStream(streamid);
519 }
520
521 inline static void ADDON_DemuxReset(const AddonInstance_InputStream* instance)
522 {
523 instance->toAddon.addonInstance->DemuxReset();
524 }
525
526 inline static void ADDON_DemuxAbort(const AddonInstance_InputStream* instance)
527 {
528 instance->toAddon.addonInstance->DemuxAbort();
529 }
530
531 inline static void ADDON_DemuxFlush(const AddonInstance_InputStream* instance)
532 {
533 instance->toAddon.addonInstance->DemuxFlush();
534 }
535
536 inline static DemuxPacket* ADDON_DemuxRead(const AddonInstance_InputStream* instance)
537 {
538 return instance->toAddon.addonInstance->DemuxRead();
539 }
540
541 inline static bool ADDON_DemuxSeekTime(const AddonInstance_InputStream* instance, double time, bool backwards, double *startpts)
542 {
543 return instance->toAddon.addonInstance->DemuxSeekTime(time, backwards, *startpts);
544 }
545
546 inline static void ADDON_DemuxSetSpeed(const AddonInstance_InputStream* instance, int speed)
547 {
548 instance->toAddon.addonInstance->DemuxSetSpeed(speed);
549 }
550
551 inline static void ADDON_SetVideoResolution(const AddonInstance_InputStream* instance, int width, int height)
552 {
553 instance->toAddon.addonInstance->SetVideoResolution(width, height);
554 }
555
556
557 // IDisplayTime
558 inline static int ADDON_GetTotalTime(const AddonInstance_InputStream* instance)
559 {
560 return instance->toAddon.addonInstance->GetTotalTime();
561 }
562
563 inline static int ADDON_GetTime(const AddonInstance_InputStream* instance)
564 {
565 return instance->toAddon.addonInstance->GetTime();
566 }
567
568
569 // IPosTime
570 inline static bool ADDON_PosTime(const AddonInstance_InputStream* instance, int ms)
571 {
572 return instance->toAddon.addonInstance->PosTime(ms);
573 }
574
575 // Seekable (mandatory)
576 inline static bool ADDON_CanPauseStream(const AddonInstance_InputStream* instance)
577 {
578 return instance->toAddon.addonInstance->CanPauseStream();
579 }
580
581 inline static bool ADDON_CanSeekStream(const AddonInstance_InputStream* instance)
582 {
583 return instance->toAddon.addonInstance->CanSeekStream();
584 }
585
586
587 inline static int ADDON_ReadStream(const AddonInstance_InputStream* instance, uint8_t* buffer, unsigned int bufferSize)
588 {
589 return instance->toAddon.addonInstance->ReadStream(buffer, bufferSize);
590 }
591
592 inline static int64_t ADDON_SeekStream(const AddonInstance_InputStream* instance, int64_t position, int whence)
593 {
594 return instance->toAddon.addonInstance->SeekStream(position, whence);
595 }
596
597 inline static int64_t ADDON_PositionStream(const AddonInstance_InputStream* instance)
598 {
599 return instance->toAddon.addonInstance->PositionStream();
600 }
601
602 inline static int64_t ADDON_LengthStream(const AddonInstance_InputStream* instance)
603 {
604 return instance->toAddon.addonInstance->LengthStream();
605 }
606
607 inline static void ADDON_PauseStream(const AddonInstance_InputStream* instance, double time)
608 {
609 instance->toAddon.addonInstance->PauseStream(time);
610 }
611
612 inline static bool ADDON_IsRealTimeStream(const AddonInstance_InputStream* instance)
613 {
614 return instance->toAddon.addonInstance->IsRealTimeStream();
615 }
616
617 AddonInstance_InputStream* m_instanceData;
618 };
619
620} /* namespace addon */
621} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h
new file mode 100644
index 0000000..631b9b4
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Peripheral.h
@@ -0,0 +1,682 @@
1#pragma once
2/*
3 * Copyright (C) 2014-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this Program; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include "../AddonBase.h"
23
24namespace kodi { namespace addon { class CInstancePeripheral; }}
25
26/* indicates a joystick has no preference for port number */
27#define NO_PORT_REQUESTED (-1)
28
29/* joystick's driver button/hat/axis index is unknown */
30#define DRIVER_INDEX_UNKNOWN (-1)
31
32extern "C"
33{
34
35 /// @name Peripheral types
36 ///{
37 typedef enum PERIPHERAL_ERROR
38 {
39 PERIPHERAL_NO_ERROR = 0, // no error occurred
40 PERIPHERAL_ERROR_UNKNOWN = -1, // an unknown error occurred
41 PERIPHERAL_ERROR_FAILED = -2, // the command failed
42 PERIPHERAL_ERROR_INVALID_PARAMETERS = -3, // the parameters of the method are invalid for this operation
43 PERIPHERAL_ERROR_NOT_IMPLEMENTED = -4, // the method that the frontend called is not implemented
44 PERIPHERAL_ERROR_NOT_CONNECTED = -5, // no peripherals are connected
45 PERIPHERAL_ERROR_CONNECTION_FAILED = -6, // peripherals are connected, but command was interrupted
46 } PERIPHERAL_ERROR;
47
48 typedef enum PERIPHERAL_TYPE
49 {
50 PERIPHERAL_TYPE_UNKNOWN,
51 PERIPHERAL_TYPE_JOYSTICK,
52 PERIPHERAL_TYPE_KEYBOARD,
53 } PERIPHERAL_TYPE;
54
55 typedef struct PERIPHERAL_INFO
56 {
57 PERIPHERAL_TYPE type; /*!< @brief type of peripheral */
58 char* name; /*!< @brief name of peripheral */
59 uint16_t vendor_id; /*!< @brief vendor ID of peripheral, 0x0000 if unknown */
60 uint16_t product_id; /*!< @brief product ID of peripheral, 0x0000 if unknown */
61 unsigned int index; /*!< @brief the order in which the add-on identified this peripheral */
62 } ATTRIBUTE_PACKED PERIPHERAL_INFO;
63
64 /*!
65 * @brief Peripheral add-on capabilities.
66 * If a capability is set to true, then the corresponding methods from
67 * kodi_peripheral_dll.h need to be implemented.
68 */
69 typedef struct PERIPHERAL_CAPABILITIES
70 {
71 bool provides_joysticks; /*!< @brief true if the add-on provides joysticks */
72 bool provides_joystick_rumble;
73 bool provides_joystick_power_off;
74 bool provides_buttonmaps; /*!< @brief true if the add-on provides button maps */
75 } ATTRIBUTE_PACKED PERIPHERAL_CAPABILITIES;
76 ///}
77
78 /// @name Event types
79 ///{
80 typedef enum PERIPHERAL_EVENT_TYPE
81 {
82 PERIPHERAL_EVENT_TYPE_NONE, /*!< @brief unknown event */
83 PERIPHERAL_EVENT_TYPE_DRIVER_BUTTON, /*!< @brief state changed for joystick driver button */
84 PERIPHERAL_EVENT_TYPE_DRIVER_HAT, /*!< @brief state changed for joystick driver hat */
85 PERIPHERAL_EVENT_TYPE_DRIVER_AXIS, /*!< @brief state changed for joystick driver axis */
86 PERIPHERAL_EVENT_TYPE_SET_MOTOR, /*!< @brief set the state for joystick rumble motor */
87 } PERIPHERAL_EVENT_TYPE;
88
89 typedef enum JOYSTICK_STATE_BUTTON
90 {
91 JOYSTICK_STATE_BUTTON_UNPRESSED = 0x0, /*!< @brief button is released */
92 JOYSTICK_STATE_BUTTON_PRESSED = 0x1, /*!< @brief button is pressed */
93 } JOYSTICK_STATE_BUTTON;
94
95 typedef enum JOYSTICK_STATE_HAT
96 {
97 JOYSTICK_STATE_HAT_UNPRESSED = 0x0, /*!< @brief no directions are pressed */
98 JOYSTICK_STATE_HAT_LEFT = 0x1, /*!< @brief only left is pressed */
99 JOYSTICK_STATE_HAT_RIGHT = 0x2, /*!< @brief only right is pressed */
100 JOYSTICK_STATE_HAT_UP = 0x4, /*!< @brief only up is pressed */
101 JOYSTICK_STATE_HAT_DOWN = 0x8, /*!< @brief only down is pressed */
102 JOYSTICK_STATE_HAT_LEFT_UP = JOYSTICK_STATE_HAT_LEFT | JOYSTICK_STATE_HAT_UP,
103 JOYSTICK_STATE_HAT_LEFT_DOWN = JOYSTICK_STATE_HAT_LEFT | JOYSTICK_STATE_HAT_DOWN,
104 JOYSTICK_STATE_HAT_RIGHT_UP = JOYSTICK_STATE_HAT_RIGHT | JOYSTICK_STATE_HAT_UP,
105 JOYSTICK_STATE_HAT_RIGHT_DOWN = JOYSTICK_STATE_HAT_RIGHT | JOYSTICK_STATE_HAT_DOWN,
106 } JOYSTICK_STATE_HAT;
107
108 /*!
109 * @brief value in the closed interval [-1.0, 1.0]
110 *
111 * The axis state uses the XInput coordinate system:
112 * - Negative values signify down or to the left
113 * - Positive values signify up or to the right
114 */
115 typedef float JOYSTICK_STATE_AXIS;
116
117 typedef float JOYSTICK_STATE_MOTOR;
118
119 typedef struct PERIPHERAL_EVENT
120 {
121 unsigned int peripheral_index;
122 PERIPHERAL_EVENT_TYPE type;
123 unsigned int driver_index;
124 JOYSTICK_STATE_BUTTON driver_button_state;
125 JOYSTICK_STATE_HAT driver_hat_state;
126 JOYSTICK_STATE_AXIS driver_axis_state;
127 JOYSTICK_STATE_MOTOR motor_state;
128 } ATTRIBUTE_PACKED PERIPHERAL_EVENT;
129 ///}
130
131 /// @name Joystick types
132 ///{
133 typedef struct JOYSTICK_INFO
134 {
135 PERIPHERAL_INFO peripheral; /*!< @brief peripheral info for this joystick */
136 char* provider; /*!< @brief name of the driver or interface providing the joystick */
137 int requested_port; /*!< @brief requested port number (such as for 360 controllers), or NO_PORT_REQUESTED */
138 unsigned int button_count; /*!< @brief number of buttons reported by the driver */
139 unsigned int hat_count; /*!< @brief number of hats reported by the driver */
140 unsigned int axis_count; /*!< @brief number of axes reported by the driver */
141 unsigned int motor_count; /*!< @brief number of motors reported by the driver */
142 bool supports_poweroff; /*!< @brief whether the joystick supports being powered off */
143 } ATTRIBUTE_PACKED JOYSTICK_INFO;
144
145 typedef enum JOYSTICK_DRIVER_PRIMITIVE_TYPE
146 {
147 JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN,
148 JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON,
149 JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION,
150 JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS,
151 JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR,
152 } JOYSTICK_DRIVER_PRIMITIVE_TYPE;
153
154 typedef struct JOYSTICK_DRIVER_BUTTON
155 {
156 int index;
157 } ATTRIBUTE_PACKED JOYSTICK_DRIVER_BUTTON;
158
159 typedef enum JOYSTICK_DRIVER_HAT_DIRECTION
160 {
161 JOYSTICK_DRIVER_HAT_UNKNOWN,
162 JOYSTICK_DRIVER_HAT_LEFT,
163 JOYSTICK_DRIVER_HAT_RIGHT,
164 JOYSTICK_DRIVER_HAT_UP,
165 JOYSTICK_DRIVER_HAT_DOWN,
166 } JOYSTICK_DRIVER_HAT_DIRECTION;
167
168 typedef struct JOYSTICK_DRIVER_HAT
169 {
170 int index;
171 JOYSTICK_DRIVER_HAT_DIRECTION direction;
172 } ATTRIBUTE_PACKED JOYSTICK_DRIVER_HAT;
173
174 typedef enum JOYSTICK_DRIVER_SEMIAXIS_DIRECTION
175 {
176 JOYSTICK_DRIVER_SEMIAXIS_NEGATIVE = -1, /*!< @brief negative half of the axis */
177 JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN = 0, /*!< @brief unknown direction */
178 JOYSTICK_DRIVER_SEMIAXIS_POSITIVE = 1, /*!< @brief positive half of the axis */
179 } JOYSTICK_DRIVER_SEMIAXIS_DIRECTION;
180
181 typedef struct JOYSTICK_DRIVER_SEMIAXIS
182 {
183 int index;
184 int center;
185 JOYSTICK_DRIVER_SEMIAXIS_DIRECTION direction;
186 unsigned int range;
187 } ATTRIBUTE_PACKED JOYSTICK_DRIVER_SEMIAXIS;
188
189 typedef struct JOYSTICK_DRIVER_MOTOR
190 {
191 int index;
192 } ATTRIBUTE_PACKED JOYSTICK_DRIVER_MOTOR;
193
194 typedef struct JOYSTICK_DRIVER_PRIMITIVE
195 {
196 JOYSTICK_DRIVER_PRIMITIVE_TYPE type;
197 union
198 {
199 struct JOYSTICK_DRIVER_BUTTON button;
200 struct JOYSTICK_DRIVER_HAT hat;
201 struct JOYSTICK_DRIVER_SEMIAXIS semiaxis;
202 struct JOYSTICK_DRIVER_MOTOR motor;
203 };
204 } ATTRIBUTE_PACKED JOYSTICK_DRIVER_PRIMITIVE;
205
206 typedef enum JOYSTICK_FEATURE_TYPE
207 {
208 JOYSTICK_FEATURE_TYPE_UNKNOWN,
209 JOYSTICK_FEATURE_TYPE_SCALAR,
210 JOYSTICK_FEATURE_TYPE_ANALOG_STICK,
211 JOYSTICK_FEATURE_TYPE_ACCELEROMETER,
212 JOYSTICK_FEATURE_TYPE_MOTOR,
213 } JOYSTICK_FEATURE_TYPE;
214
215 typedef enum JOYSTICK_FEATURE_PRIMITIVE
216 {
217 // Scalar feature
218 JOYSTICK_SCALAR_PRIMITIVE = 0,
219
220 // Analog stick
221 JOYSTICK_ANALOG_STICK_UP = 0,
222 JOYSTICK_ANALOG_STICK_DOWN = 1,
223 JOYSTICK_ANALOG_STICK_RIGHT = 2,
224 JOYSTICK_ANALOG_STICK_LEFT = 3,
225
226 // Accelerometer
227 JOYSTICK_ACCELEROMETER_POSITIVE_X = 0,
228 JOYSTICK_ACCELEROMETER_POSITIVE_Y = 1,
229 JOYSTICK_ACCELEROMETER_POSITIVE_Z = 2,
230
231 // Motor
232 JOYSTICK_MOTOR_PRIMITIVE = 0,
233
234 // Maximum number of primitives
235 JOYSTICK_PRIMITIVE_MAX = 4,
236 } JOYSTICK_FEATURE_PRIMITIVE;
237
238 typedef struct JOYSTICK_FEATURE
239 {
240 char* name;
241 JOYSTICK_FEATURE_TYPE type;
242 struct JOYSTICK_DRIVER_PRIMITIVE primitives[JOYSTICK_PRIMITIVE_MAX];
243 } ATTRIBUTE_PACKED JOYSTICK_FEATURE;
244 ///}
245
246 typedef struct AddonProps_Peripheral
247 {
248 const char* user_path; /*!< @brief path to the user profile */
249 const char* addon_path; /*!< @brief path to this add-on */
250 } ATTRIBUTE_PACKED AddonProps_Peripheral;
251
252 struct AddonInstance_Peripheral;
253
254 typedef struct AddonToKodiFuncTable_Peripheral
255 {
256 KODI_HANDLE kodiInstance;
257 void (*trigger_scan)(void* kodiInstance);
258 void (*refresh_button_maps)(void* kodiInstance, const char* device_name, const char* controller_id);
259 unsigned int (*feature_count)(void* kodiInstance, const char* controller_id, JOYSTICK_FEATURE_TYPE type);
260 } AddonToKodiFuncTable_Peripheral;
261
262 //! @todo Mouse, light gun, multitouch
263
264 typedef struct KodiToAddonFuncTable_Peripheral
265 {
266 kodi::addon::CInstancePeripheral* addonInstance;
267
268 void (__cdecl* get_capabilities)(const AddonInstance_Peripheral* addonInstance, PERIPHERAL_CAPABILITIES* capabilities);
269 PERIPHERAL_ERROR (__cdecl* perform_device_scan)(const AddonInstance_Peripheral* addonInstance, unsigned int* peripheral_count, PERIPHERAL_INFO** scan_results);
270 void (__cdecl* free_scan_results)(const AddonInstance_Peripheral* addonInstance, unsigned int peripheral_count, PERIPHERAL_INFO* scan_results);
271 PERIPHERAL_ERROR (__cdecl* get_events)(const AddonInstance_Peripheral* addonInstance, unsigned int* event_count, PERIPHERAL_EVENT** events);
272 void (__cdecl* free_events)(const AddonInstance_Peripheral* addonInstance, unsigned int event_count, PERIPHERAL_EVENT* events);
273 bool (__cdecl* send_event)(const AddonInstance_Peripheral* addonInstance, const PERIPHERAL_EVENT* event);
274
275 /// @name Joystick operations
276 ///{
277 PERIPHERAL_ERROR (__cdecl* get_joystick_info)(const AddonInstance_Peripheral* addonInstance, unsigned int index, JOYSTICK_INFO* info);
278 void (__cdecl* free_joystick_info)(const AddonInstance_Peripheral* addonInstance, JOYSTICK_INFO* info);
279 PERIPHERAL_ERROR (__cdecl* get_features)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, const char* controller_id, unsigned int* feature_count, JOYSTICK_FEATURE** features);
280 void (__cdecl* free_features)(const AddonInstance_Peripheral* addonInstance, unsigned int feature_count, JOYSTICK_FEATURE* features);
281 PERIPHERAL_ERROR (__cdecl* map_features)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, const char* controller_id, unsigned int feature_count, const JOYSTICK_FEATURE* features);
282 PERIPHERAL_ERROR (__cdecl* get_ignored_primitives)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, unsigned int* feature_count, JOYSTICK_DRIVER_PRIMITIVE** primitives);
283 void (__cdecl* free_primitives)(const AddonInstance_Peripheral* addonInstance, unsigned int, JOYSTICK_DRIVER_PRIMITIVE* primitives);
284 PERIPHERAL_ERROR (__cdecl* set_ignored_primitives)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, unsigned int primitive_count, const JOYSTICK_DRIVER_PRIMITIVE* primitives);
285 void (__cdecl* save_button_map)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick);
286 void (__cdecl* revert_button_map)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick);
287 void (__cdecl* reset_button_map)(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, const char* controller_id);
288 void (__cdecl* power_off_joystick)(const AddonInstance_Peripheral* addonInstance, unsigned int index);
289 ///}
290 } KodiToAddonFuncTable_Peripheral;
291
292 typedef struct AddonInstance_Peripheral
293 {
294 AddonProps_Peripheral props;
295 AddonToKodiFuncTable_Peripheral toKodi;
296 KodiToAddonFuncTable_Peripheral toAddon;
297 } AddonInstance_Peripheral;
298
299} /* extern "C" */
300
301namespace kodi
302{
303namespace addon
304{
305
306 class CInstancePeripheral : public IAddonInstance
307 {
308 public:
309 CInstancePeripheral()
310 : IAddonInstance(ADDON_INSTANCE_PERIPHERAL)
311 {
312 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
313 throw std::logic_error("kodi::addon::CInstancePeripheral: Creation of more as one in single instance way is not allowed!");
314
315 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance);
316 CAddonBase::m_interface->globalSingleInstance = this;
317 }
318
319 CInstancePeripheral(KODI_HANDLE instance)
320 : IAddonInstance(ADDON_INSTANCE_PERIPHERAL)
321 {
322 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
323 throw std::logic_error("kodi::addon::CInstancePeripheral: Creation of multiple together with single instance way is not allowed!");
324
325 SetAddonStruct(instance);
326 }
327
328 ~CInstancePeripheral() override = default;
329
330 /// @name Peripheral operations
331 ///{
332 /*!
333 * @brief Get the list of features that this add-on provides
334 * @param capabilities The add-on's capabilities.
335 * @remarks Valid implementation required.
336 *
337 * Called by the frontend to query the add-on's capabilities and supported
338 * peripherals. All capabilities that the add-on supports should be set to true.
339 *
340 */
341 virtual void GetCapabilities(PERIPHERAL_CAPABILITIES &capabilities) { }
342
343 /*!
344 * @brief Perform a scan for joysticks
345 * @param peripheral_count Assigned to the number of peripherals allocated
346 * @param scan_results Assigned to allocated memory
347 * @return PERIPHERAL_NO_ERROR if successful; peripherals must be freed using
348 * FreeScanResults() in this case
349 *
350 * The frontend calls this when a hardware change is detected. If an add-on
351 * detects a hardware change, it can trigger this function using the
352 * TriggerScan() callback.
353 */
354 virtual PERIPHERAL_ERROR PerformDeviceScan(unsigned int* peripheral_count, PERIPHERAL_INFO** scan_results) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
355
356 /*!
357 * @brief Free the memory allocated in PerformDeviceScan()
358 *
359 * Must be called if PerformDeviceScan() returns PERIPHERAL_NO_ERROR.
360 *
361 * @param peripheral_count The number of events allocated for the events array
362 * @param scan_results The array of allocated peripherals
363 */
364 virtual void FreeScanResults(unsigned int peripheral_count, PERIPHERAL_INFO* scan_results) { }
365
366 /*!
367 * @brief Get all events that have occurred since the last call to GetEvents()
368 * @return PERIPHERAL_NO_ERROR if successful; events must be freed using
369 * FreeEvents() in this case
370 */
371 virtual PERIPHERAL_ERROR GetEvents(unsigned int* event_count, PERIPHERAL_EVENT** events) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
372
373 /*!
374 * @brief Free the memory allocated in GetEvents()
375 *
376 * Must be called if GetEvents() returns PERIPHERAL_NO_ERROR.
377 *
378 * @param event_count The number of events allocated for the events array
379 * @param events The array of allocated events
380 */
381 virtual void FreeEvents(unsigned int event_count, PERIPHERAL_EVENT* events) { }
382
383 /*!
384 * @brief Send an input event to the specified peripheral
385 * @param peripheralIndex The index of the device receiving the input event
386 * @param event The input event
387 * @return true if the event was handled, false otherwise
388 */
389 virtual bool SendEvent(const PERIPHERAL_EVENT* event) { return false; }
390 ///}
391
392 /// @name Joystick operations
393 /*!
394 * @note #define PERIPHERAL_ADDON_JOYSTICKS before including kodi_peripheral_dll.h
395 * in the add-on if the add-on provides joysticks and add provides_joysticks="true"
396 * to the kodi.peripheral extension point node in addon.xml.
397 */
398 ///{
399 /*!
400 * @brief Get extended info about an attached joystick
401 * @param index The joystick's driver index
402 * @param info The container for the allocated joystick info
403 * @return PERIPHERAL_NO_ERROR if successful; array must be freed using
404 * FreeJoystickInfo() in this case
405 */
406 virtual PERIPHERAL_ERROR GetJoystickInfo(unsigned int index, JOYSTICK_INFO* info) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
407
408 /*!
409 * @brief Free the memory allocated in GetJoystickInfo()
410 */
411 virtual void FreeJoystickInfo(JOYSTICK_INFO* info) { }
412
413 /*!
414 * @brief Get the features that allow translating the joystick into the controller profile
415 * @param joystick The device's joystick properties; unknown values may be left at their default
416 * @param controller_id The controller profile being requested, e.g. game.controller.default
417 * @param feature_count The number of features allocated for the features array
418 * @param features The array of allocated features
419 * @return PERIPHERAL_NO_ERROR if successful; array must be freed using
420 * FreeButtonMap() in this case
421 */
422 virtual PERIPHERAL_ERROR GetFeatures(const JOYSTICK_INFO* joystick, const char* controller_id,
423 unsigned int* feature_count, JOYSTICK_FEATURE** features) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
424
425 /*!
426 * @brief Free the memory allocated in GetFeatures()
427 *
428 * Must be called if GetFeatures() returns PERIPHERAL_NO_ERROR.
429 *
430 * @param feature_count The number of features allocated for the features array
431 * @param features The array of allocated features
432 */
433 virtual void FreeFeatures(unsigned int feature_count, JOYSTICK_FEATURE* features) { }
434
435 /*!
436 * @brief Add or update joystick features
437 * @param joystick The device's joystick properties; unknown values may be left at their default
438 * @param controller_id The game controller profile being updated
439 * @param feature_count The number of features in the features array
440 * @param features The array of features
441 * @return PERIPHERAL_NO_ERROR if successful
442 */
443 virtual PERIPHERAL_ERROR MapFeatures(const JOYSTICK_INFO* joystick, const char* controller_id,
444 unsigned int feature_count, const JOYSTICK_FEATURE* features) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
445
446 /*!
447 * @brief Get the driver primitives that should be ignored while mapping the device
448 * @param joystick The device's joystick properties; unknown values may be left at their default
449 * @param primitive_count The number of features allocated for the primitives array
450 * @param primitives The array of allocated driver primitives to be ignored
451 * @return PERIPHERAL_NO_ERROR if successful; array must be freed using
452 * FreePrimitives() in this case
453 */
454 virtual PERIPHERAL_ERROR GetIgnoredPrimitives(const JOYSTICK_INFO* joystick,
455 unsigned int* primitive_count,
456 JOYSTICK_DRIVER_PRIMITIVE** primitives) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
457
458 /*!
459 * @brief Free the memory allocated in GetIgnoredPrimitives()
460 *
461 * Must be called if GetIgnoredPrimitives() returns PERIPHERAL_NO_ERROR.
462 *
463 * @param primitive_count The number of driver primitives allocated for the primitives array
464 * @param primitives The array of allocated driver primitives
465 */
466 virtual void FreePrimitives(unsigned int primitive_count, JOYSTICK_DRIVER_PRIMITIVE* primitives) { }
467
468 /*!
469 * @brief Set the list of driver primitives that are ignored for the device
470 * @param joystick The device's joystick properties; unknown values may be left at their default
471 * @param primitive_count The number of driver features in the primitives array
472 * @param primitives The array of driver primitives to ignore
473 * @return PERIPHERAL_NO_ERROR if successful
474 */
475 virtual PERIPHERAL_ERROR SetIgnoredPrimitives(const JOYSTICK_INFO* joystick,
476 unsigned int primitive_count,
477 const JOYSTICK_DRIVER_PRIMITIVE* primitives) { return PERIPHERAL_ERROR_NOT_IMPLEMENTED; }
478
479 /*!
480 * @brief Save the button map for the given joystick
481 * @param joystick The device's joystick properties
482 */
483 virtual void SaveButtonMap(const JOYSTICK_INFO* joystick) { }
484
485 /*!
486 * @brief Revert the button map to the last time it was loaded or committed to disk
487 * @param joystick The device's joystick properties
488 */
489 virtual void RevertButtonMap(const JOYSTICK_INFO* joystick) { }
490
491 /*!
492 * @brief Reset the button map for the given joystick and controller profile ID
493 * @param joystick The device's joystick properties
494 * @param controller_id The game controller profile being reset
495 */
496 virtual void ResetButtonMap(const JOYSTICK_INFO* joystick, const char* controller_id) { }
497
498 /*!
499 * @brief Powers off the given joystick if supported
500 * @param index The joystick's driver index
501 */
502 virtual void PowerOffJoystick(unsigned int index) { }
503
504 const std::string AddonPath() const
505 {
506 return m_instanceData->props.addon_path;
507 }
508
509 const std::string UserPath() const
510 {
511 return m_instanceData->props.user_path;
512 }
513
514 /*!
515 * @brief Trigger a scan for peripherals
516 *
517 * The add-on calls this if a change in hardware is detected.
518 */
519 void TriggerScan(void)
520 {
521 return m_instanceData->toKodi.trigger_scan(m_instanceData->toKodi.kodiInstance);
522 }
523
524 /*!
525 * @brief Notify the frontend that button maps have changed
526 *
527 * @param[optional] deviceName The name of the device to refresh, or empty/null for all devices
528 * @param[optional] controllerId The controller ID to refresh, or empty/null for all controllers
529 */
530 void RefreshButtonMaps(const std::string& strDeviceName = "", const std::string& strControllerId = "")
531 {
532 return m_instanceData->toKodi.refresh_button_maps(m_instanceData->toKodi.kodiInstance, strDeviceName.c_str(), strControllerId.c_str());
533 }
534
535 /*!
536 * @brief Return the number of features belonging to the specified controller
537 *
538 * @param controllerId The controller ID to enumerate
539 * @param type[optional] Type to filter by, or JOYSTICK_FEATURE_TYPE_UNKNOWN for all features
540 *
541 * @return The number of features matching the request parameters
542 */
543 unsigned int FeatureCount(const std::string& strControllerId, JOYSTICK_FEATURE_TYPE type = JOYSTICK_FEATURE_TYPE_UNKNOWN)
544 {
545 return m_instanceData->toKodi.feature_count(m_instanceData->toKodi.kodiInstance, strControllerId.c_str(), type);
546 }
547
548 private:
549 void SetAddonStruct(KODI_HANDLE instance)
550 {
551 if (instance == nullptr)
552 throw std::logic_error("kodi::addon::CInstancePeripheral: Creation with empty addon structure not allowed, table must be given from Kodi!");
553
554 m_instanceData = static_cast<AddonInstance_Peripheral*>(instance);
555 m_instanceData->toAddon.addonInstance = this;
556
557 m_instanceData->toAddon.get_capabilities = ADDON_GetCapabilities;
558 m_instanceData->toAddon.perform_device_scan = ADDON_PerformDeviceScan;
559 m_instanceData->toAddon.free_scan_results = ADDON_FreeScanResults;
560 m_instanceData->toAddon.get_events = ADDON_GetEvents;
561 m_instanceData->toAddon.free_events = ADDON_FreeEvents;
562 m_instanceData->toAddon.send_event = ADDON_SendEvent;
563
564 m_instanceData->toAddon.get_joystick_info = ADDON_GetJoystickInfo;
565 m_instanceData->toAddon.free_joystick_info = ADDON_FreeJoystickInfo;
566 m_instanceData->toAddon.get_features = ADDON_GetFeatures;
567 m_instanceData->toAddon.free_features = ADDON_FreeFeatures;
568 m_instanceData->toAddon.map_features = ADDON_MapFeatures;
569 m_instanceData->toAddon.get_ignored_primitives = ADDON_GetIgnoredPrimitives;
570 m_instanceData->toAddon.free_primitives = ADDON_FreePrimitives;
571 m_instanceData->toAddon.set_ignored_primitives = ADDON_SetIgnoredPrimitives;
572 m_instanceData->toAddon.save_button_map = ADDON_SaveButtonMap;
573 m_instanceData->toAddon.revert_button_map = ADDON_RevertButtonMap;
574 m_instanceData->toAddon.reset_button_map = ADDON_ResetButtonMap;
575 m_instanceData->toAddon.power_off_joystick = ADDON_PowerOffJoystick;
576 }
577
578 inline static void ADDON_GetCapabilities(const AddonInstance_Peripheral* addonInstance, PERIPHERAL_CAPABILITIES *capabilities)
579 {
580 addonInstance->toAddon.addonInstance->GetCapabilities(*capabilities);
581 }
582
583 inline static PERIPHERAL_ERROR ADDON_PerformDeviceScan(const AddonInstance_Peripheral* addonInstance, unsigned int* peripheral_count, PERIPHERAL_INFO** scan_results)
584 {
585 return addonInstance->toAddon.addonInstance->PerformDeviceScan(peripheral_count, scan_results);
586 }
587
588 inline static void ADDON_FreeScanResults(const AddonInstance_Peripheral* addonInstance, unsigned int peripheral_count, PERIPHERAL_INFO* scan_results)
589 {
590 addonInstance->toAddon.addonInstance->FreeScanResults(peripheral_count, scan_results);
591 }
592
593 inline static PERIPHERAL_ERROR ADDON_GetEvents(const AddonInstance_Peripheral* addonInstance, unsigned int* event_count, PERIPHERAL_EVENT** events)
594 {
595 return addonInstance->toAddon.addonInstance->GetEvents(event_count, events);
596 }
597
598 inline static void ADDON_FreeEvents(const AddonInstance_Peripheral* addonInstance, unsigned int event_count, PERIPHERAL_EVENT* events)
599 {
600 addonInstance->toAddon.addonInstance->FreeEvents(event_count, events);
601 }
602
603 inline static bool ADDON_SendEvent(const AddonInstance_Peripheral* addonInstance, const PERIPHERAL_EVENT* event)
604 {
605 return addonInstance->toAddon.addonInstance->SendEvent(event);
606 }
607
608
609 inline static PERIPHERAL_ERROR ADDON_GetJoystickInfo(const AddonInstance_Peripheral* addonInstance, unsigned int index, JOYSTICK_INFO* info)
610 {
611 return addonInstance->toAddon.addonInstance->GetJoystickInfo(index, info);
612 }
613
614 inline static void ADDON_FreeJoystickInfo(const AddonInstance_Peripheral* addonInstance, JOYSTICK_INFO* info)
615 {
616 addonInstance->toAddon.addonInstance->FreeJoystickInfo(info);
617 }
618
619 inline static PERIPHERAL_ERROR ADDON_GetFeatures(const AddonInstance_Peripheral* addonInstance,
620 const JOYSTICK_INFO* joystick, const char* controller_id,
621 unsigned int* feature_count, JOYSTICK_FEATURE** features)
622 {
623 return addonInstance->toAddon.addonInstance->GetFeatures(joystick, controller_id, feature_count, features);
624 }
625
626 inline static void ADDON_FreeFeatures(const AddonInstance_Peripheral* addonInstance, unsigned int feature_count, JOYSTICK_FEATURE* features)
627 {
628 addonInstance->toAddon.addonInstance->FreeFeatures(feature_count, features);
629 }
630
631 inline static PERIPHERAL_ERROR ADDON_MapFeatures(const AddonInstance_Peripheral* addonInstance,
632 const JOYSTICK_INFO* joystick, const char* controller_id,
633 unsigned int feature_count, const JOYSTICK_FEATURE* features)
634 {
635 return addonInstance->toAddon.addonInstance->MapFeatures(joystick, controller_id, feature_count, features);
636 }
637
638 inline static PERIPHERAL_ERROR ADDON_GetIgnoredPrimitives(const AddonInstance_Peripheral* addonInstance,
639 const JOYSTICK_INFO* joystick, unsigned int* primitive_count,
640 JOYSTICK_DRIVER_PRIMITIVE** primitives)
641 {
642 return addonInstance->toAddon.addonInstance->GetIgnoredPrimitives(joystick, primitive_count, primitives);
643 }
644
645 inline static void ADDON_FreePrimitives(const AddonInstance_Peripheral* addonInstance,
646 unsigned int primitive_count, JOYSTICK_DRIVER_PRIMITIVE* primitives)
647 {
648 addonInstance->toAddon.addonInstance->FreePrimitives(primitive_count, primitives);
649 }
650
651 inline static PERIPHERAL_ERROR ADDON_SetIgnoredPrimitives(const AddonInstance_Peripheral* addonInstance,
652 const JOYSTICK_INFO* joystick, unsigned int primitive_count,
653 const JOYSTICK_DRIVER_PRIMITIVE* primitives)
654 {
655 return addonInstance->toAddon.addonInstance->SetIgnoredPrimitives(joystick, primitive_count, primitives);
656 }
657
658 inline static void ADDON_SaveButtonMap(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick)
659 {
660 addonInstance->toAddon.addonInstance->SaveButtonMap(joystick);
661 }
662
663 inline static void ADDON_RevertButtonMap(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick)
664 {
665 addonInstance->toAddon.addonInstance->RevertButtonMap(joystick);
666 }
667
668 inline static void ADDON_ResetButtonMap(const AddonInstance_Peripheral* addonInstance, const JOYSTICK_INFO* joystick, const char* controller_id)
669 {
670 addonInstance->toAddon.addonInstance->ResetButtonMap(joystick, controller_id);
671 }
672
673 inline static void ADDON_PowerOffJoystick(const AddonInstance_Peripheral* addonInstance, unsigned int index)
674 {
675 addonInstance->toAddon.addonInstance->PowerOffJoystick(index);
676 }
677
678 AddonInstance_Peripheral* m_instanceData;
679 };
680
681} /* namespace addon */
682} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h
new file mode 100644
index 0000000..8cfa91b
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/PeripheralUtils.h
@@ -0,0 +1,668 @@
1/*
2 * Copyright (C) 2014-2017 Team Kodi
3 * http://kodi.tv
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this Program; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20#pragma once
21
22#include "Peripheral.h"
23
24#include <array> // Requires c++11
25#include <cstring>
26#include <map>
27#include <string>
28#include <vector>
29
30#define PERIPHERAL_SAFE_DELETE(x) do { delete (x); (x) = NULL; } while (0)
31#define PERIPHERAL_SAFE_DELETE_ARRAY(x) do { delete[] (x); (x) = NULL; } while (0)
32
33namespace kodi
34{
35namespace addon
36{
37 /*!
38 * Utility class to manipulate arrays of peripheral types.
39 */
40 template <class THE_CLASS, typename THE_STRUCT>
41 class PeripheralVector
42 {
43 public:
44 static void ToStructs(const std::vector<THE_CLASS>& vecObjects, THE_STRUCT** pStructs)
45 {
46 if (!pStructs)
47 return;
48
49 if (vecObjects.empty())
50 {
51 *pStructs = NULL;
52 }
53 else
54 {
55 (*pStructs) = new THE_STRUCT[vecObjects.size()];
56 for (unsigned int i = 0; i < vecObjects.size(); i++)
57 vecObjects.at(i).ToStruct((*pStructs)[i]);
58 }
59 }
60
61 static void ToStructs(const std::vector<THE_CLASS*>& vecObjects, THE_STRUCT** pStructs)
62 {
63 if (!pStructs)
64 return;
65
66 if (vecObjects.empty())
67 {
68 *pStructs = NULL;
69 }
70 else
71 {
72 *pStructs = new THE_STRUCT[vecObjects.size()];
73 for (unsigned int i = 0; i < vecObjects.size(); i++)
74 vecObjects.at(i)->ToStruct((*pStructs)[i]);
75 }
76 }
77
78 static void FreeStructs(unsigned int structCount, THE_STRUCT* structs)
79 {
80 if (structs)
81 {
82 for (unsigned int i = 0; i < structCount; i++)
83 THE_CLASS::FreeStruct(structs[i]);
84 }
85 PERIPHERAL_SAFE_DELETE_ARRAY(structs);
86 }
87 };
88
89 /*!
90 * ADDON::Peripheral
91 *
92 * Wrapper class providing peripheral information. Classes can extend
93 * Peripheral to inherit peripheral properties.
94 */
95 class Peripheral
96 {
97 public:
98 Peripheral(PERIPHERAL_TYPE type = PERIPHERAL_TYPE_UNKNOWN, const std::string& strName = "") :
99 m_type(type),
100 m_strName(strName),
101 m_vendorId(0),
102 m_productId(0),
103 m_index(0)
104 {
105 }
106
107 Peripheral(const PERIPHERAL_INFO& info) :
108 m_type(info.type),
109 m_strName(info.name ? info.name : ""),
110 m_vendorId(info.vendor_id),
111 m_productId(info.product_id),
112 m_index(info.index)
113 {
114 }
115
116 virtual ~Peripheral(void) = default;
117
118 PERIPHERAL_TYPE Type(void) const { return m_type; }
119 const std::string& Name(void) const { return m_strName; }
120 uint16_t VendorID(void) const { return m_vendorId; }
121 uint16_t ProductID(void) const { return m_productId; }
122 unsigned int Index(void) const { return m_index; }
123
124 // Derived property: VID and PID are 0x0000 if unknown
125 bool IsVidPidKnown(void) const { return m_vendorId != 0 || m_productId != 0; }
126
127 void SetType(PERIPHERAL_TYPE type) { m_type = type; }
128 void SetName(const std::string& strName) { m_strName = strName; }
129 void SetVendorID(uint16_t vendorId) { m_vendorId = vendorId; }
130 void SetProductID(uint16_t productId) { m_productId = productId; }
131 void SetIndex(unsigned int index) { m_index = index; }
132
133 void ToStruct(PERIPHERAL_INFO& info) const
134 {
135 info.type = m_type;
136 info.name = new char[m_strName.size() + 1];
137 info.vendor_id = m_vendorId;
138 info.product_id = m_productId;
139 info.index = m_index;
140
141 std::strcpy(info.name, m_strName.c_str());
142 }
143
144 static void FreeStruct(PERIPHERAL_INFO& info)
145 {
146 PERIPHERAL_SAFE_DELETE_ARRAY(info.name);
147 }
148
149 private:
150 PERIPHERAL_TYPE m_type;
151 std::string m_strName;
152 uint16_t m_vendorId;
153 uint16_t m_productId;
154 unsigned int m_index;
155 };
156
157 typedef PeripheralVector<Peripheral, PERIPHERAL_INFO> Peripherals;
158
159 /*!
160 * ADDON::PeripheralEvent
161 *
162 * Wrapper class for peripheral events.
163 */
164 class PeripheralEvent
165 {
166 public:
167 PeripheralEvent(void) :
168 m_event()
169 {
170 }
171
172 PeripheralEvent(unsigned int peripheralIndex, unsigned int buttonIndex, JOYSTICK_STATE_BUTTON state) :
173 m_event()
174 {
175 SetType(PERIPHERAL_EVENT_TYPE_DRIVER_BUTTON);
176 SetPeripheralIndex(peripheralIndex);
177 SetDriverIndex(buttonIndex);
178 SetButtonState(state);
179 }
180
181 PeripheralEvent(unsigned int peripheralIndex, unsigned int hatIndex, JOYSTICK_STATE_HAT state) :
182 m_event()
183 {
184 SetType(PERIPHERAL_EVENT_TYPE_DRIVER_HAT);
185 SetPeripheralIndex(peripheralIndex);
186 SetDriverIndex(hatIndex);
187 SetHatState(state);
188 }
189
190 PeripheralEvent(unsigned int peripheralIndex, unsigned int axisIndex, JOYSTICK_STATE_AXIS state) :
191 m_event()
192 {
193 SetType(PERIPHERAL_EVENT_TYPE_DRIVER_AXIS);
194 SetPeripheralIndex(peripheralIndex);
195 SetDriverIndex(axisIndex);
196 SetAxisState(state);
197 }
198
199 PeripheralEvent(const PERIPHERAL_EVENT& event) :
200 m_event(event)
201 {
202 }
203
204 PERIPHERAL_EVENT_TYPE Type(void) const { return m_event.type; }
205 unsigned int PeripheralIndex(void) const { return m_event.peripheral_index; }
206 unsigned int DriverIndex(void) const { return m_event.driver_index; }
207 JOYSTICK_STATE_BUTTON ButtonState(void) const { return m_event.driver_button_state; }
208 JOYSTICK_STATE_HAT HatState(void) const { return m_event.driver_hat_state; }
209 JOYSTICK_STATE_AXIS AxisState(void) const { return m_event.driver_axis_state; }
210 JOYSTICK_STATE_MOTOR MotorState(void) const { return m_event.motor_state; }
211
212 void SetType(PERIPHERAL_EVENT_TYPE type) { m_event.type = type; }
213 void SetPeripheralIndex(unsigned int index) { m_event.peripheral_index = index; }
214 void SetDriverIndex(unsigned int index) { m_event.driver_index = index; }
215 void SetButtonState(JOYSTICK_STATE_BUTTON state) { m_event.driver_button_state = state; }
216 void SetHatState(JOYSTICK_STATE_HAT state) { m_event.driver_hat_state = state; }
217 void SetAxisState(JOYSTICK_STATE_AXIS state) { m_event.driver_axis_state = state; }
218 void SetMotorState(JOYSTICK_STATE_MOTOR state) { m_event.motor_state = state; }
219
220 void ToStruct(PERIPHERAL_EVENT& event) const
221 {
222 event = m_event;
223 }
224
225 static void FreeStruct(PERIPHERAL_EVENT& event)
226 {
227 (void)event;
228 }
229
230 private:
231 PERIPHERAL_EVENT m_event;
232 };
233
234 typedef PeripheralVector<PeripheralEvent, PERIPHERAL_EVENT> PeripheralEvents;
235
236 /*!
237 * kodi::addon::Joystick
238 *
239 * Wrapper class providing additional joystick information not provided by
240 * ADDON::Peripheral.
241 */
242 class Joystick : public Peripheral
243 {
244 public:
245 Joystick(const std::string& provider = "", const std::string& strName = "") :
246 Peripheral(PERIPHERAL_TYPE_JOYSTICK, strName),
247 m_provider(provider),
248 m_requestedPort(NO_PORT_REQUESTED),
249 m_buttonCount(0),
250 m_hatCount(0),
251 m_axisCount(0),
252 m_motorCount(0),
253 m_supportsPowerOff(false)
254 {
255 }
256
257 Joystick(const Joystick& other)
258 {
259 *this = other;
260 }
261
262 Joystick(const JOYSTICK_INFO& info) :
263 Peripheral(info.peripheral),
264 m_provider(info.provider ? info.provider : ""),
265 m_requestedPort(info.requested_port),
266 m_buttonCount(info.button_count),
267 m_hatCount(info.hat_count),
268 m_axisCount(info.axis_count),
269 m_motorCount(info.motor_count),
270 m_supportsPowerOff(info.supports_poweroff)
271 {
272 }
273
274 ~Joystick(void) override = default;
275
276 Joystick& operator=(const Joystick& rhs)
277 {
278 if (this != &rhs)
279 {
280 Peripheral::operator=(rhs);
281
282 m_provider = rhs.m_provider;
283 m_requestedPort = rhs.m_requestedPort;
284 m_buttonCount = rhs.m_buttonCount;
285 m_hatCount = rhs.m_hatCount;
286 m_axisCount = rhs.m_axisCount;
287 m_motorCount = rhs.m_motorCount;
288 m_supportsPowerOff = rhs.m_supportsPowerOff;
289 }
290 return *this;
291 }
292
293 const std::string& Provider(void) const { return m_provider; }
294 int RequestedPort(void) const { return m_requestedPort; }
295 unsigned int ButtonCount(void) const { return m_buttonCount; }
296 unsigned int HatCount(void) const { return m_hatCount; }
297 unsigned int AxisCount(void) const { return m_axisCount; }
298 unsigned int MotorCount(void) const { return m_motorCount; }
299 bool SupportsPowerOff(void) const { return m_supportsPowerOff; }
300
301 // Derived property: Counts are unknown if all are zero
302 bool AreElementCountsKnown(void) const { return m_buttonCount != 0 || m_hatCount != 0 || m_axisCount != 0; }
303
304 void SetProvider(const std::string& provider) { m_provider = provider; }
305 void SetRequestedPort(int requestedPort) { m_requestedPort = requestedPort; }
306 void SetButtonCount(unsigned int buttonCount) { m_buttonCount = buttonCount; }
307 void SetHatCount(unsigned int hatCount) { m_hatCount = hatCount; }
308 void SetAxisCount(unsigned int axisCount) { m_axisCount = axisCount; }
309 void SetMotorCount(unsigned int motorCount) { m_motorCount = motorCount; }
310 void SetSupportsPowerOff(bool supportsPowerOff) { m_supportsPowerOff = supportsPowerOff; }
311
312 void ToStruct(JOYSTICK_INFO& info) const
313 {
314 Peripheral::ToStruct(info.peripheral);
315
316 info.provider = new char[m_provider.size() + 1];
317 info.requested_port = m_requestedPort;
318 info.button_count = m_buttonCount;
319 info.hat_count = m_hatCount;
320 info.axis_count = m_axisCount;
321 info.motor_count = m_motorCount;
322 info.supports_poweroff = m_supportsPowerOff;
323
324 std::strcpy(info.provider, m_provider.c_str());
325 }
326
327 static void FreeStruct(JOYSTICK_INFO& info)
328 {
329 Peripheral::FreeStruct(info.peripheral);
330
331 PERIPHERAL_SAFE_DELETE_ARRAY(info.provider);
332 }
333
334 private:
335 std::string m_provider;
336 int m_requestedPort;
337 unsigned int m_buttonCount;
338 unsigned int m_hatCount;
339 unsigned int m_axisCount;
340 unsigned int m_motorCount;
341 bool m_supportsPowerOff;
342 };
343
344 typedef PeripheralVector<Joystick, JOYSTICK_INFO> Joysticks;
345
346 /*!
347 * ADDON::DriverPrimitive
348 *
349 * Base class for joystick driver primitives. A driver primitive can be:
350 *
351 * 1) a button
352 * 2) a hat direction
353 * 3) a semiaxis (either the positive or negative half of an axis)
354 * 4) a motor
355 *
356 * The type determines the fields in use:
357 *
358 * Button:
359 * - driver index
360 *
361 * Hat direction:
362 * - driver index
363 * - hat direction
364 *
365 * Semiaxis:
366 * - driver index
367 * - center
368 * - semiaxis direction
369 * - range
370 *
371 * Motor:
372 * - driver index
373 */
374 struct DriverPrimitive
375 {
376 protected:
377 /*!
378 * \brief Construct a driver primitive of the specified type
379 */
380 DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE type, unsigned int driverIndex) :
381 m_type(type),
382 m_driverIndex(driverIndex),
383 m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN),
384 m_center(0),
385 m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN),
386 m_range(1)
387 {
388 }
389
390 public:
391 /*!
392 * \brief Construct an invalid driver primitive
393 */
394 DriverPrimitive(void) :
395 m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_UNKNOWN),
396 m_driverIndex(0),
397 m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN),
398 m_center(0),
399 m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN),
400 m_range(1)
401 {
402 }
403
404 /*!
405 * \brief Construct a driver primitive representing a button
406 */
407 static DriverPrimitive CreateButton(unsigned int buttonIndex)
408 {
409 return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON, buttonIndex);
410 }
411
412 /*!
413 * \brief Construct a driver primitive representing one of the four direction
414 * arrows on a dpad
415 */
416 DriverPrimitive(unsigned int hatIndex, JOYSTICK_DRIVER_HAT_DIRECTION direction) :
417 m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION),
418 m_driverIndex(hatIndex),
419 m_hatDirection(direction),
420 m_center(0),
421 m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN),
422 m_range(1)
423 {
424 }
425
426 /*!
427 * \brief Construct a driver primitive representing the positive or negative
428 * half of an axis
429 */
430 DriverPrimitive(unsigned int axisIndex, int center, JOYSTICK_DRIVER_SEMIAXIS_DIRECTION direction, unsigned int range) :
431 m_type(JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS),
432 m_driverIndex(axisIndex),
433 m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN),
434 m_center(center),
435 m_semiAxisDirection(direction),
436 m_range(range)
437 {
438 }
439
440 /*!
441 * \brief Construct a driver primitive representing a motor
442 */
443 static DriverPrimitive CreateMotor(unsigned int motorIndex)
444 {
445 return DriverPrimitive(JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR, motorIndex);
446 }
447
448 DriverPrimitive(const JOYSTICK_DRIVER_PRIMITIVE& primitive) :
449 m_type(primitive.type),
450 m_driverIndex(0),
451 m_hatDirection(JOYSTICK_DRIVER_HAT_UNKNOWN),
452 m_center(0),
453 m_semiAxisDirection(JOYSTICK_DRIVER_SEMIAXIS_UNKNOWN),
454 m_range(1)
455 {
456 switch (m_type)
457 {
458 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON:
459 {
460 m_driverIndex = primitive.button.index;
461 break;
462 }
463 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION:
464 {
465 m_driverIndex = primitive.hat.index;
466 m_hatDirection = primitive.hat.direction;
467 break;
468 }
469 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS:
470 {
471 m_driverIndex = primitive.semiaxis.index;
472 m_center = primitive.semiaxis.center;
473 m_semiAxisDirection = primitive.semiaxis.direction;
474 m_range = primitive.semiaxis.range;
475 break;
476 }
477 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR:
478 {
479 m_driverIndex = primitive.motor.index;
480 break;
481 }
482 default:
483 break;
484 }
485 }
486
487 JOYSTICK_DRIVER_PRIMITIVE_TYPE Type(void) const { return m_type; }
488 unsigned int DriverIndex(void) const { return m_driverIndex; }
489 JOYSTICK_DRIVER_HAT_DIRECTION HatDirection(void) const { return m_hatDirection; }
490 int Center(void) const { return m_center; }
491 JOYSTICK_DRIVER_SEMIAXIS_DIRECTION SemiAxisDirection(void) const { return m_semiAxisDirection; }
492 unsigned int Range(void) const { return m_range; }
493
494 bool operator==(const DriverPrimitive& other) const
495 {
496 if (m_type == other.m_type)
497 {
498 switch (m_type)
499 {
500 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON:
501 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR:
502 {
503 return m_driverIndex == other.m_driverIndex;
504 }
505 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION:
506 {
507 return m_driverIndex == other.m_driverIndex &&
508 m_hatDirection == other.m_hatDirection;
509 }
510 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS:
511 {
512 return m_driverIndex == other.m_driverIndex &&
513 m_center == other.m_center &&
514 m_semiAxisDirection == other.m_semiAxisDirection &&
515 m_range == other.m_range;
516 }
517 default:
518 break;
519 }
520 }
521 return false;
522 }
523
524 void ToStruct(JOYSTICK_DRIVER_PRIMITIVE& driver_primitive) const
525 {
526 driver_primitive.type = m_type;
527 switch (m_type)
528 {
529 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_BUTTON:
530 {
531 driver_primitive.button.index = m_driverIndex;
532 break;
533 }
534 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_HAT_DIRECTION:
535 {
536 driver_primitive.hat.index = m_driverIndex;
537 driver_primitive.hat.direction = m_hatDirection;
538 break;
539 }
540 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_SEMIAXIS:
541 {
542 driver_primitive.semiaxis.index = m_driverIndex;
543 driver_primitive.semiaxis.center = m_center;
544 driver_primitive.semiaxis.direction = m_semiAxisDirection;
545 driver_primitive.semiaxis.range = m_range;
546 break;
547 }
548 case JOYSTICK_DRIVER_PRIMITIVE_TYPE_MOTOR:
549 {
550 driver_primitive.motor.index = m_driverIndex;
551 break;
552 }
553 default:
554 break;
555 }
556 }
557
558 static void FreeStruct(JOYSTICK_DRIVER_PRIMITIVE& primitive)
559 {
560 (void)primitive;
561 }
562
563 private:
564 JOYSTICK_DRIVER_PRIMITIVE_TYPE m_type;
565 unsigned int m_driverIndex;
566 JOYSTICK_DRIVER_HAT_DIRECTION m_hatDirection;
567 int m_center;
568 JOYSTICK_DRIVER_SEMIAXIS_DIRECTION m_semiAxisDirection;
569 unsigned int m_range;
570 };
571
572 typedef PeripheralVector<DriverPrimitive, JOYSTICK_DRIVER_PRIMITIVE> DriverPrimitives;
573
574 /*!
575 * kodi::addon::JoystickFeature
576 *
577 * Class for joystick features. A feature can be:
578 *
579 * 1) scalar[1]
580 * 2) analog stick
581 * 3) accelerometer
582 * 4) motor
583 *
584 * [1] All three driver primitives (buttons, hats and axes) have a state that
585 * can be represented using a single scalar value. For this reason,
586 * features that map to a single primitive are called "scalar features".
587 */
588 class JoystickFeature
589 {
590 public:
591 JoystickFeature(const std::string& name = "", JOYSTICK_FEATURE_TYPE type = JOYSTICK_FEATURE_TYPE_UNKNOWN) :
592 m_name(name),
593 m_type(type),
594 m_primitives()
595 {
596 }
597
598 JoystickFeature(const JoystickFeature& other)
599 {
600 *this = other;
601 }
602
603 JoystickFeature(const JOYSTICK_FEATURE& feature) :
604 m_name(feature.name ? feature.name : ""),
605 m_type(feature.type)
606 {
607 for (unsigned int i = 0; i < JOYSTICK_PRIMITIVE_MAX; i++)
608 m_primitives[i] = feature.primitives[i];
609 }
610
611 JoystickFeature& operator=(const JoystickFeature& rhs)
612 {
613 if (this != &rhs)
614 {
615 m_name = rhs.m_name;
616 m_type = rhs.m_type;
617 m_primitives = rhs.m_primitives;
618 }
619 return *this;
620 }
621
622 bool operator==(const JoystickFeature& other) const
623 {
624 return m_name == other.m_name &&
625 m_type == other.m_type &&
626 m_primitives == other.m_primitives;
627 }
628
629 const std::string& Name(void) const { return m_name; }
630 JOYSTICK_FEATURE_TYPE Type(void) const { return m_type; }
631 bool IsValid() const { return m_type != JOYSTICK_FEATURE_TYPE_UNKNOWN; }
632
633 void SetName(const std::string& name) { m_name = name; }
634 void SetType(JOYSTICK_FEATURE_TYPE type) { m_type = type; }
635 void SetInvalid(void) { m_type = JOYSTICK_FEATURE_TYPE_UNKNOWN; }
636
637 const DriverPrimitive& Primitive(JOYSTICK_FEATURE_PRIMITIVE which) const { return m_primitives[which]; }
638 void SetPrimitive(JOYSTICK_FEATURE_PRIMITIVE which, const DriverPrimitive& primitive) { m_primitives[which] = primitive; }
639
640 std::array<DriverPrimitive, JOYSTICK_PRIMITIVE_MAX>& Primitives() { return m_primitives; }
641 const std::array<DriverPrimitive, JOYSTICK_PRIMITIVE_MAX>& Primitives() const { return m_primitives; }
642
643 void ToStruct(JOYSTICK_FEATURE& feature) const
644 {
645 feature.name = new char[m_name.length() + 1];
646 feature.type = m_type;
647 for (unsigned int i = 0; i < JOYSTICK_PRIMITIVE_MAX; i++)
648 m_primitives[i].ToStruct(feature.primitives[i]);
649
650 std::strcpy(feature.name, m_name.c_str());
651 }
652
653 static void FreeStruct(JOYSTICK_FEATURE& feature)
654 {
655 PERIPHERAL_SAFE_DELETE_ARRAY(feature.name);
656 }
657
658 private:
659 std::string m_name;
660 JOYSTICK_FEATURE_TYPE m_type;
661 std::array<DriverPrimitive, JOYSTICK_PRIMITIVE_MAX> m_primitives;
662 };
663
664 typedef PeripheralVector<JoystickFeature, JOYSTICK_FEATURE> JoystickFeatures;
665
666} /* namespace addon */
667} /* namespace kodi */
668
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h
index 39baae7..85cd7bc 100644
--- a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Screensaver.h
@@ -28,6 +28,11 @@ extern "C"
28 28
29struct AddonInstance_Screensaver; 29struct AddonInstance_Screensaver;
30 30
31/*!
32 * @brief Screensaver properties
33 *
34 * Not to be used outside this header.
35 */
31typedef struct AddonProps_Screensaver 36typedef struct AddonProps_Screensaver
32{ 37{
33 void *device; 38 void *device;
@@ -41,11 +46,21 @@ typedef struct AddonProps_Screensaver
41 const char *profile; 46 const char *profile;
42} AddonProps_Screensaver; 47} AddonProps_Screensaver;
43 48
49/*!
50 * @brief Screensaver callbacks
51 *
52 * Not to be used outside this header.
53 */
44typedef struct AddonToKodiFuncTable_Screensaver 54typedef struct AddonToKodiFuncTable_Screensaver
45{ 55{
46 KODI_HANDLE kodiInstance; 56 KODI_HANDLE kodiInstance;
47} AddonToKodiFuncTable_Screensaver; 57} AddonToKodiFuncTable_Screensaver;
48 58
59/*!
60 * @brief Screensaver function hooks
61 *
62 * Not to be used outside this header.
63 */
49typedef struct KodiToAddonFuncTable_Screensaver 64typedef struct KodiToAddonFuncTable_Screensaver
50{ 65{
51 kodi::addon::CInstanceScreensaver* addonInstance; 66 kodi::addon::CInstanceScreensaver* addonInstance;
@@ -54,6 +69,11 @@ typedef struct KodiToAddonFuncTable_Screensaver
54 void (__cdecl* Render) (AddonInstance_Screensaver* instance); 69 void (__cdecl* Render) (AddonInstance_Screensaver* instance);
55} KodiToAddonFuncTable_Screensaver; 70} KodiToAddonFuncTable_Screensaver;
56 71
72/*!
73 * @brief Screensaver instance
74 *
75 * Not to be used outside this header.
76 */
57typedef struct AddonInstance_Screensaver 77typedef struct AddonInstance_Screensaver
58{ 78{
59 AddonProps_Screensaver props; 79 AddonProps_Screensaver props;
@@ -68,9 +88,157 @@ namespace kodi
68namespace addon 88namespace addon
69{ 89{
70 90
91 //============================================================================
92 ///
93 /// \addtogroup cpp_kodi_addon_screensaver
94 /// @brief \cpp_class{ kodi::addon::CInstanceScreensaver }
95 /// **Screensaver add-on instance**
96 ///
97 /// A screensaver is a Kodi addon that fills the screen with moving images or
98 /// patterns when the computer is not in use. Initially designed to prevent
99 /// phosphor burn-in on CRT and plasma computer monitors (hence the name),
100 /// screensavers are now used primarily for entertainment, security or to
101 /// display system status information.
102 ///
103 /// Include the header \ref ScreenSaver.h "#include <kodi/addon-instance/ScreenSaver.h>"
104 /// to use this class.
105 ///
106 /// This interface allows the creating of screensavers for Kodi, based upon
107 /// **DirectX** or/and **OpenGL** rendering with `C++` code.
108 ///
109 /// The interface is small and easy usable. It has three functions:
110 ///
111 /// * <b><c>Start()</c></b> - Called on creation
112 /// * <b><c>Render()</c></b> - Called at render time
113 /// * <b><c>Stop()</c></b> - Called when the screensaver has no work
114 ///
115 /// Additionally, there are several \ref cpp_kodi_addon_screensaver_CB "other functions"
116 /// available in which the child class can ask about the current hardware,
117 /// including the device, display and several other parts.
118 ///
119 ///
120 /// --------------------------------------------------------------------------
121 ///
122 ///
123 /// **Here is an example of the minimum required code to start a screensaver:**
124 /// ~~~~~~~~~~~~~{.cpp}
125 /// #include <kodi/addon-instance/Screensaver.h>
126 ///
127 /// class CMyScreenSaver : public kodi::addon::CAddonBase,
128 /// public kodi::addon::CInstanceScreensaver
129 /// {
130 /// public:
131 /// CMyScreenSaver();
132 ///
133 /// bool Start() override;
134 /// void Render() override;
135 /// };
136 ///
137 /// CMyScreenSaver::CMyScreenSaver()
138 /// {
139 /// ...
140 /// }
141 ///
142 /// bool CMyScreenSaver::Start()
143 /// {
144 /// ...
145 /// return true;
146 /// }
147 ///
148 /// void CMyScreenSaver::Render()
149 /// {
150 /// ...
151 /// }
152 ///
153 /// ADDONCREATOR(CMyScreenSaver)
154 /// ~~~~~~~~~~~~~
155 ///
156 ///
157 /// --------------------------------------------------------------------------
158 ///
159 ///
160 /// **Here is another example where the screensaver is used together with
161 /// other instance types:**
162 ///
163 /// ~~~~~~~~~~~~~{.cpp}
164 /// #include <kodi/addon-instance/Screensaver.h>
165 ///
166 /// class CMyScreenSaver : public ::kodi::addon::CInstanceScreensaver
167 /// {
168 /// public:
169 /// CMyScreenSaver(KODI_HANDLE instance);
170 ///
171 /// bool Start() override;
172 /// void Render() override;
173 /// };
174 ///
175 /// CMyScreenSaver::CMyScreenSaver(KODI_HANDLE instance)
176 /// : CInstanceScreensaver(instance)
177 /// {
178 /// ...
179 /// }
180 ///
181 /// bool CMyScreenSaver::Start()
182 /// {
183 /// ...
184 /// return true;
185 /// }
186 ///
187 /// void CMyScreenSaver::Render()
188 /// {
189 /// ...
190 /// }
191 ///
192 ///
193 /// /*----------------------------------------------------------------------*/
194 ///
195 /// class CMyAddon : public ::kodi::addon::CAddonBase
196 /// {
197 /// public:
198 /// CMyAddon() { }
199 /// ADDON_STATUS CreateInstance(int instanceType,
200 /// std::string instanceID,
201 /// KODI_HANDLE instance,
202 /// KODI_HANDLE& addonInstance) override;
203 /// };
204 ///
205 /// /* If you use only one instance in your add-on, can be instanceType and
206 /// * instanceID ignored */
207 /// ADDON_STATUS CMyAddon::CreateInstance(int instanceType,
208 /// std::string instanceID,
209 /// KODI_HANDLE instance,
210 /// KODI_HANDLE& addonInstance)
211 /// {
212 /// if (instanceType == ADDON_INSTANCE_SCREENSAVER)
213 /// {
214 /// kodi::Log(ADDON_LOG_NOTICE, "Creating my Screensaver");
215 /// addonInstance = new CMyScreenSaver(instance);
216 /// return ADDON_STATUS_OK;
217 /// }
218 /// else if (...)
219 /// {
220 /// ...
221 /// }
222 /// return ADDON_STATUS_UNKNOWN;
223 /// }
224 ///
225 /// ADDONCREATOR(CMyAddon)
226 /// ~~~~~~~~~~~~~
227 ///
228 /// The destruction of the example class `CMyScreenSaver` is called from
229 /// Kodi's header. Manually deleting the add-on instance is not required.
230 ///
231 //----------------------------------------------------------------------------
71 class CInstanceScreensaver : public IAddonInstance 232 class CInstanceScreensaver : public IAddonInstance
72 { 233 {
73 public: 234 public:
235 //==========================================================================
236 ///
237 /// @ingroup cpp_kodi_addon_screensaver
238 /// @brief Screensaver class constructor
239 ///
240 /// Used by an add-on that only supports screensavers.
241 ///
74 CInstanceScreensaver() 242 CInstanceScreensaver()
75 : IAddonInstance(ADDON_INSTANCE_SCREENSAVER) 243 : IAddonInstance(ADDON_INSTANCE_SCREENSAVER)
76 { 244 {
@@ -80,7 +248,19 @@ namespace addon
80 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance); 248 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance);
81 CAddonBase::m_interface->globalSingleInstance = this; 249 CAddonBase::m_interface->globalSingleInstance = this;
82 } 250 }
251 //--------------------------------------------------------------------------
83 252
253 //==========================================================================
254 ///
255 /// @ingroup cpp_kodi_addon_screensaver
256 /// @brief Screensaver class constructor used to support multiple instance
257 /// types
258 ///
259 /// @param[in] instance The instance value given to
260 /// <b>`kodi::addon::CAddonBase::CreateInstance(...)`</b>.
261 ///
262 /// @warning Only use `instance` from the CreateInstance call
263 ///
84 CInstanceScreensaver(KODI_HANDLE instance) 264 CInstanceScreensaver(KODI_HANDLE instance)
85 : IAddonInstance(ADDON_INSTANCE_SCREENSAVER) 265 : IAddonInstance(ADDON_INSTANCE_SCREENSAVER)
86 { 266 {
@@ -89,22 +269,150 @@ namespace addon
89 269
90 SetAddonStruct(instance); 270 SetAddonStruct(instance);
91 } 271 }
272 //--------------------------------------------------------------------------
92 273
93 virtual ~CInstanceScreensaver() { } 274 //==========================================================================
275 ///
276 /// @ingroup cpp_kodi_addon_screensaver
277 /// @brief Destructor
278 ///
279 ~CInstanceScreensaver() override = default;
280 //--------------------------------------------------------------------------
94 281
282 //==========================================================================
283 ///
284 /// @ingroup cpp_kodi_addon_screensaver
285 /// @brief Used to notify the screensaver that it has been started
286 ///
287 /// @return true if the screensaver was started
288 /// successfully, false otherwise
289 ///
95 virtual bool Start() { return true; } 290 virtual bool Start() { return true; }
291 //--------------------------------------------------------------------------
292
293 //==========================================================================
294 ///
295 /// @ingroup cpp_kodi_addon_screensaver
296 /// @brief Used to inform the screensaver that the rendering control was
297 /// stopped
298 ///
96 virtual void Stop() {} 299 virtual void Stop() {}
300 //--------------------------------------------------------------------------
301
302 //==========================================================================
303 ///
304 /// @ingroup cpp_kodi_addon_screensaver
305 /// @brief Used to indicate when the add-on should render
306 ///
97 virtual void Render() {} 307 virtual void Render() {}
308 //--------------------------------------------------------------------------
98 309
310 //==========================================================================
311 ///
312 /// \defgroup cpp_kodi_addon_screensaver_CB Information functions
313 /// \ingroup cpp_kodi_addon_screensaver
314 /// @brief **To get info about the device, display and several other parts**
315 ///
316 //@{
317
318 //==========================================================================
319 ///
320 /// @ingroup cpp_kodi_addon_screensaver_CB
321 /// @brief Device that represents the display adapter
322 ///
323 /// @return A pointer to the device
324 ///
325 /// @note This is only available on **DirectX**, It us unused (`nullptr`) on
326 /// **OpenGL**
327 ///
99 inline void* Device() { return m_instanceData->props.device; } 328 inline void* Device() { return m_instanceData->props.device; }
329 //--------------------------------------------------------------------------
330
331 //==========================================================================
332 ///
333 /// @ingroup cpp_kodi_addon_screensaver_CB
334 /// @brief Returns the X position of the rendering window
335 ///
336 /// @return The X position, in pixels
337 ///
100 inline int X() { return m_instanceData->props.x; } 338 inline int X() { return m_instanceData->props.x; }
339 //--------------------------------------------------------------------------
340
341 //==========================================================================
342 ///
343 /// @ingroup cpp_kodi_addon_screensaver_CB
344 /// @brief Returns the Y position of the rendering window
345 ///
346 /// @return The Y position, in pixels
347 ///
101 inline int Y() { return m_instanceData->props.y; } 348 inline int Y() { return m_instanceData->props.y; }
349 //--------------------------------------------------------------------------
350
351 //==========================================================================
352 ///
353 /// @ingroup cpp_kodi_addon_screensaver_CB
354 /// @brief Returns the width of the rendering window
355 ///
356 /// @return The width, in pixels
357 ///
102 inline int Width() { return m_instanceData->props.width; } 358 inline int Width() { return m_instanceData->props.width; }
359 //--------------------------------------------------------------------------
360
361 //==========================================================================
362 ///
363 /// @ingroup cpp_kodi_addon_screensaver_CB
364 /// @brief Returns the height of the rendering window
365 ///
366 /// @return The height, in pixels
367 ///
103 inline int Height() { return m_instanceData->props.height; } 368 inline int Height() { return m_instanceData->props.height; }
369 //--------------------------------------------------------------------------
370
371 //==========================================================================
372 ///
373 /// @ingroup cpp_kodi_addon_screensaver_CB
374 /// @brief Pixel aspect ratio (often abbreviated PAR) is a ratio that
375 /// describes how the width of a pixel compares to the height of that pixel.
376 ///
377 /// @return The pixel aspect ratio used by the display
378 ///
104 inline float PixelRatio() { return m_instanceData->props.pixelRatio; } 379 inline float PixelRatio() { return m_instanceData->props.pixelRatio; }
380 //--------------------------------------------------------------------------
381
382 //==========================================================================
383 ///
384 /// @ingroup cpp_kodi_addon_screensaver_CB
385 /// @brief Used to get the name of the add-on defined in `addon.xml`
386 ///
387 /// @return The add-on name
388 ///
105 inline std::string Name() { return m_instanceData->props.name; } 389 inline std::string Name() { return m_instanceData->props.name; }
390 //--------------------------------------------------------------------------
391
392 //==========================================================================
393 ///
394 /// @ingroup cpp_kodi_addon_screensaver_CB
395 /// @brief Used to get the full path where the add-on is installed
396 ///
397 /// @return The add-on installation path
398 ///
106 inline std::string Presets() { return m_instanceData->props.presets; } 399 inline std::string Presets() { return m_instanceData->props.presets; }
400 //--------------------------------------------------------------------------
401
402 //==========================================================================
403 ///
404 /// @ingroup cpp_kodi_addon_screensaver_CB
405 /// @brief Used to get the full path to the add-on's user profile
406 ///
407 /// @note The trailing folder (consisting of the add-on's ID) is not created
408 /// by default. If it is needed, you must call kodi::vfs::CreateDirectory()
409 /// to create the folder.
410 ///
411 /// @return Path to the user profile
412 ///
107 inline std::string Profile() { return m_instanceData->props.profile; } 413 inline std::string Profile() { return m_instanceData->props.profile; }
414 //--------------------------------------------------------------------------
415 //@}
108 416
109 private: 417 private:
110 void SetAddonStruct(KODI_HANDLE instance) 418 void SetAddonStruct(KODI_HANDLE instance)
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
new file mode 100644
index 0000000..4bb3e69
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VFS.h
@@ -0,0 +1,622 @@
1#pragma once
2/*
3 * Copyright (C) 2015 Team Kodi
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Kodi; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include "../AddonBase.h"
22#include "../Filesystem.h"
23
24#ifdef BUILD_KODI_ADDON
25#include "../IFileTypes.h"
26#else
27#include "filesystem/IFileTypes.h"
28#include "PlatformDefs.h"
29#endif
30
31namespace kodi { namespace addon { class CInstanceVFS; }}
32
33extern "C"
34{
35
36 struct VFSURL
37 {
38 const char* url;
39 const char* domain;
40 const char* hostname;
41 const char* filename;
42 unsigned int port;
43 const char* options;
44 const char* username;
45 const char* password;
46 const char* redacted;
47 const char* sharename;
48 };
49
50 typedef struct VFSGetDirectoryCallbacks /* internal */
51 {
52 bool (__cdecl* get_keyboard_input)(void* ctx, const char* heading, char** input, bool hidden_input);
53 void (__cdecl* set_error_dialog)(void* ctx, const char* heading, const char* line1, const char* line2, const char* line3);
54 void (__cdecl* require_authentication)(void* ctx, const char* url);
55 void* ctx;
56 } VFSGetDirectoryCallbacks;
57
58 typedef struct AddonProps_VFSEntry /* internal */
59 {
60 int dummy;
61 } AddonProps_VFSEntry;
62
63 typedef struct AddonToKodiFuncTable_VFSEntry /* internal */
64 {
65 KODI_HANDLE kodiInstance;
66 } AddonToKodiFuncTable_VFSEntry;
67
68 struct AddonInstance_VFSEntry;
69 typedef struct KodiToAddonFuncTable_VFSEntry /* internal */
70 {
71 kodi::addon::CInstanceVFS* addonInstance;
72
73 void* (__cdecl* open) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
74 void* (__cdecl* open_for_write) (const AddonInstance_VFSEntry* instance, const VFSURL* url, bool overwrite);
75 ssize_t (__cdecl* read) (const AddonInstance_VFSEntry* instance, void* context, void* buffer, size_t buf_size);
76 ssize_t (__cdecl* write) (const AddonInstance_VFSEntry* instance, void* context, const void* buffer, size_t buf_size);
77 int64_t (__cdecl* seek) (const AddonInstance_VFSEntry* instance, void* context, int64_t position, int whence);
78 int (__cdecl* truncate) (const AddonInstance_VFSEntry* instance, void* context, int64_t size);
79 int64_t (__cdecl* get_length) (const AddonInstance_VFSEntry* instance, void* context);
80 int64_t (__cdecl* get_position) (const AddonInstance_VFSEntry* instance, void* context);
81 int (__cdecl* get_chunk_size) (const AddonInstance_VFSEntry* instance, void* context);
82 int (__cdecl* io_control) (const AddonInstance_VFSEntry* instance, void* context, XFILE::EIoControl request, void* param);
83 int (__cdecl* stat) (const AddonInstance_VFSEntry* instance, const VFSURL* url, struct __stat64* buffer);
84 bool (__cdecl* close) (const AddonInstance_VFSEntry* instance, void* context);
85 bool (__cdecl* exists) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
86 void (__cdecl* clear_out_idle) (const AddonInstance_VFSEntry* instance);
87 void (__cdecl* disconnect_all) (const AddonInstance_VFSEntry* instance);
88 bool (__cdecl* delete_it) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
89 bool (__cdecl* rename) (const AddonInstance_VFSEntry* instance, const VFSURL* url, const VFSURL* url2);
90 bool (__cdecl* directory_exists) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
91 bool (__cdecl* remove_directory) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
92 bool (__cdecl* create_directory) (const AddonInstance_VFSEntry* instance, const VFSURL* url);
93 bool (__cdecl* get_directory) (const AddonInstance_VFSEntry* instance,
94 const VFSURL* url,
95 VFSDirEntry** entries,
96 int* num_entries,
97 VFSGetDirectoryCallbacks* callbacks);
98 bool (__cdecl* contains_files) (const AddonInstance_VFSEntry* instance,
99 const VFSURL* url,
100 VFSDirEntry** entries,
101 int* num_entries,
102 char* rootpath);
103 void (__cdecl* free_directory) (const AddonInstance_VFSEntry* instance, VFSDirEntry* entries, int num_entries);
104 } KodiToAddonFuncTable_VFSEntry;
105
106 typedef struct AddonInstance_VFSEntry /* internal */
107 {
108 AddonProps_VFSEntry props;
109 AddonToKodiFuncTable_VFSEntry toKodi;
110 KodiToAddonFuncTable_VFSEntry toAddon;
111 } AddonInstance_VFSEntry;
112
113} /* extern "C" */
114
115namespace kodi
116{
117namespace addon
118{
119 class CInstanceVFS : public IAddonInstance
120 {
121 public:
122 CInstanceVFS(KODI_HANDLE instance)
123 : IAddonInstance(ADDON_INSTANCE_VFS)
124 {
125 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
126 throw std::logic_error("kodi::addon::CInstanceVFS: Creation of multiple together with single instance way is not allowed!");
127
128 SetAddonStruct(instance);
129 }
130
131 ~CInstanceVFS() override = default;
132
133 /// @brief Open a file for input
134 ///
135 /// @param[in] url The URL of the file
136 /// @return Context for the opened file
137 virtual void* Open(const VFSURL& url) { return nullptr; }
138
139 /// @brief Open a file for output
140 ///
141 /// @param[in] url The URL of the file
142 /// @param[in] overWrite Whether or not to overwrite an existing file
143 /// @return Context for the opened file
144 ///
145 virtual void* OpenForWrite(const VFSURL& url, bool overWrite) { return nullptr; }
146
147 /// @brief Read from a file
148 ///
149 /// @param[in] context The context of the file
150 /// @param[out] buffer The buffer to read data into
151 /// @param[in] uiBufSize Number of bytes to read
152 /// @return Number of bytes read
153 ///
154 virtual ssize_t Read(void* context, void* buffer, size_t uiBufSize) { return -1; }
155
156 /// @brief Write to a file
157 ///
158 /// @param[in] context The context of the file
159 /// @param[in] buffer The buffer to read data from
160 /// @param[in] uiBufSize Number of bytes to write
161 /// @return Number of bytes written
162 ///
163 virtual ssize_t Write(void* context, const void* buffer, size_t uiBufSize) { return -1; }
164
165 /// @brief Seek in a file
166 ///
167 /// @param[in] context The context of the file
168 /// @param[in] position The position to seek to
169 /// @param[in] whence Position in file 'position' is relative to (SEEK_CUR, SEEK_SET, SEEK_END)
170 /// @return Offset in file after seek
171 ///
172 virtual int64_t Seek(void* context, int64_t position, int whence) { return -1; }
173
174 /// @brief Truncate a file
175 ///
176 /// @param[in] context The context of the file
177 /// @param[in] size The size to truncate the file to
178 /// @return 0 on success, -1 on error
179 ///
180 virtual int Truncate(void* context, int64_t size) { return -1; }
181
182 /// @brief Get total size of a file
183 ///
184 /// @param[in] context The context of the file
185 /// @return Total file size
186 ///
187 virtual int64_t GetLength(void* context) { return 0; }
188
189 /// @brief Get current position in a file
190 ///
191 /// @param[in] context The context of the file
192 /// @return Current position
193 ///
194 virtual int64_t GetPosition(void* context) { return 0; }
195
196 /// @brief Get chunk size of a file
197 ///
198 /// @param[in] context The context of the file
199 /// @return Chunk size
200 ///
201 virtual int GetChunkSize(void* context) { return 1; }
202
203 /// @brief Perform an IO-control on the file
204 ///
205 /// @param[in] context The context of the file
206 /// @param[in] request The requested IO-control
207 /// @param[in] param Parameter attached to the IO-control
208 /// @return -1 on error, >= 0 on success
209 ///
210 virtual int IoControl(void* context, XFILE::EIoControl request, void* param) { return -1; }
211
212 /// @brief Close a file
213 ///
214 /// @param[in] context The context of the file
215 /// @return True on success, false on failure
216 ///
217 virtual bool Close(void* context) { return false; }
218
219 /// @brief Stat a file
220 ///
221 /// @param[in] url The URL of the file
222 /// @param[in] buffer The buffer to store results in
223 /// @return -1 on error, 0 otherwise
224 ///
225 virtual int Stat(const VFSURL& url, struct __stat64* buffer) { return 0; }
226
227 /// @brief Check for file existence
228 ///
229 /// @param[in] url The URL of the file
230 /// @return True if file exists, false otherwise
231 ///
232 virtual bool Exists(const VFSURL& url) { return false; }
233
234 /// @brief Clear out any idle connections
235 ///
236 virtual void ClearOutIdle() { }
237
238 /// @brief Disconnect all connections
239 ///
240 virtual void DisconnectAll() { }
241
242 /// @brief Delete a file
243 ///
244 /// @param[in] url The URL of the file
245 /// @return True if deletion was successful, false otherwise
246 ///
247 virtual bool Delete(const VFSURL& url) { return false; }
248
249 /// @brief Rename a file
250 ///
251 /// @param[in] url The URL of the source file
252 /// @param[in] url2 The URL of the destination file
253 /// @return True if deletion was successful, false otherwise
254 ///
255 virtual bool Rename(const VFSURL& url, const VFSURL& url2) { return false; }
256
257 /// @brief Check for directory existence
258 ///
259 /// @param[in] url The URL of the file
260 /// @return True if directory exists, false otherwise
261 ///
262 virtual bool DirectoryExists(const VFSURL& url) { return false; }
263
264 /// @brief Remove a directory
265 ///
266 /// @param[in] url The URL of the directory
267 /// @return True if removal was successful, false otherwise
268 ///
269 virtual bool RemoveDirectory(const VFSURL& url) { return false; }
270
271 /// @brief Create a directory
272 ///
273 /// @param[in] url The URL of the file
274 /// @return True if creation was successful, false otherwise
275 ///
276 virtual bool CreateDirectory(const VFSURL& url) { return false; }
277
278 /// @brief Callback functions on GetDirectory()
279 ///
280 /// This functions becomes available during call of GetDirectory() from
281 /// Kodi.
282 ///
283 /// If GetDirectory() returns false becomes the parts from here used on
284 /// next call of the function.
285 ///
286 /// **Example:**
287 /// ~~~~~~~~~~~~~{.cpp}
288 ///
289 /// #include <kodi/addon-instance/VFS.h>
290 ///
291 /// ...
292 ///
293 /// bool CMyFile::GetDirectory(const VFSURL& url, std::vector<kodi::vfs::CDirEntry>& items, CVFSCallbacks callbacks)
294 /// {
295 /// std::string neededString;
296 /// callbacks.GetKeyboardInput("Test", neededString, true);
297 /// if (neededString.empty())
298 /// return false;
299 ///
300 /// /* Do the work */
301 /// ...
302 /// return true;
303 /// }
304 /// ~~~~~~~~~~~~~
305 ///
306 //@{
307 class CVFSCallbacks
308 {
309 public:
310 /// @brief Require keyboard input
311 ///
312 /// Becomes called if GetDirectory() returns false and GetDirectory()
313 /// becomes after entry called again.
314 ///
315 /// @param[in] heading The heading of the keyboard dialog
316 /// @param[out] input The resulting string. Returns string after
317 /// second call!
318 /// @param[in] hiddenInput To show input only as "*" on dialog
319 /// @return True if input was received, false otherwise
320 ///
321 bool GetKeyboardInput(const std::string& heading, std::string& input, bool hiddenInput = false)
322 {
323 char* cInput = nullptr;
324 bool ret = m_cb->get_keyboard_input(m_cb->ctx, heading.c_str(), &cInput, hiddenInput);
325 if (cInput)
326 {
327 input = cInput;
328 ::kodi::addon::CAddonBase::m_interface->toKodi->free_string(::kodi::addon::CAddonBase::m_interface->toKodi->kodiBase, cInput);
329 }
330 return ret;
331 }
332
333 /// @brief Display an error dialog
334 ///
335 /// @param[in] heading The heading of the error dialog
336 /// @param[in] line1 The first line of the error dialog
337 /// @param[in] line2 [opt] The second line of the error dialog
338 /// @param[in] line3 [opt] The third line of the error dialog
339 ///
340 void SetErrorDialog(const std::string& heading, const std::string& line1, const std::string& line2 = "", const std::string& line3 = "")
341 {
342 m_cb->set_error_dialog(m_cb->ctx, heading.c_str(), line1.c_str(), line2.c_str(), line3.c_str());
343 }
344
345 /// @brief Prompt the user for authentication of a URL
346 ///
347 /// @param[in] url The URL
348 void RequireAuthentication(const std::string& url)
349 {
350 m_cb->require_authentication(m_cb->ctx, url.c_str());
351 }
352
353 CVFSCallbacks(const VFSGetDirectoryCallbacks* cb) : m_cb(cb) { }
354
355 private:
356 const VFSGetDirectoryCallbacks* m_cb;
357 };
358 //@}
359
360 /// @brief List a directory
361 ///
362 /// @param[in] url The URL of the directory
363 /// @param[out] entries The entries in the directory
364 /// @param[in] callbacks A callback structure
365 /// @return Context for the directory listing
366 ///
367 virtual bool GetDirectory(const VFSURL& url,
368 std::vector<kodi::vfs::CDirEntry>& entries,
369 CVFSCallbacks callbacks) { return false; }
370
371 /// @brief Check if file should be presented as a directory (multiple streams)
372 ///
373 /// @param[in] url The URL of the file
374 /// @param[out] entries The entries in the directory
375 /// @param[out] rootPath Path to root directory if multiple entries
376 /// @return Context for the directory listing
377 ///
378 virtual bool ContainsFiles(const VFSURL& url,
379 std::vector<kodi::vfs::CDirEntry>& entries,
380 std::string& rootPath) { return false; }
381
382 private:
383 void SetAddonStruct(KODI_HANDLE instance)
384 {
385 if (instance == nullptr)
386 throw std::logic_error("kodi::addon::CInstanceVFS: Creation with empty addon structure not allowed, table must be given from Kodi!");
387
388 m_instanceData = static_cast<AddonInstance_VFSEntry*>(instance);
389 m_instanceData->toAddon.addonInstance = this;
390 m_instanceData->toAddon.open = ADDON_Open;
391 m_instanceData->toAddon.open_for_write = ADDON_OpenForWrite;
392 m_instanceData->toAddon.read = ADDON_Read;
393 m_instanceData->toAddon.write = ADDON_Write;
394 m_instanceData->toAddon.seek = ADDON_Seek;
395 m_instanceData->toAddon.truncate = ADDON_Truncate;
396 m_instanceData->toAddon.get_length = ADDON_GetLength;
397 m_instanceData->toAddon.get_position = ADDON_GetPosition;
398 m_instanceData->toAddon.get_chunk_size = ADDON_GetChunkSize;
399 m_instanceData->toAddon.io_control = ADDON_IoControl;
400 m_instanceData->toAddon.stat = ADDON_Stat;
401 m_instanceData->toAddon.close = ADDON_Close;
402 m_instanceData->toAddon.exists = ADDON_Exists;
403 m_instanceData->toAddon.clear_out_idle = ADDON_ClearOutIdle;
404 m_instanceData->toAddon.disconnect_all = ADDON_DisconnectAll;
405 m_instanceData->toAddon.delete_it = ADDON_Delete;
406 m_instanceData->toAddon.rename = ADDON_Rename;
407 m_instanceData->toAddon.directory_exists = ADDON_DirectoryExists;
408 m_instanceData->toAddon.remove_directory = ADDON_RemoveDirectory;
409 m_instanceData->toAddon.create_directory = ADDON_CreateDirectory;
410 m_instanceData->toAddon.get_directory = ADDON_GetDirectory;
411 m_instanceData->toAddon.free_directory = ADDON_FreeDirectory;
412 m_instanceData->toAddon.contains_files = ADDON_ContainsFiles;
413 }
414
415 inline static void* ADDON_Open(const AddonInstance_VFSEntry* instance, const VFSURL* url)
416 {
417 return instance->toAddon.addonInstance->Open(*url);
418 }
419
420 inline static void* ADDON_OpenForWrite(const AddonInstance_VFSEntry* instance, const VFSURL* url, bool overWrite)
421 {
422 return instance->toAddon.addonInstance->OpenForWrite(*url, overWrite);
423 }
424
425 inline static ssize_t ADDON_Read(const AddonInstance_VFSEntry* instance, void* context, void* buffer, size_t uiBufSize)
426 {
427 return instance->toAddon.addonInstance->Read(context, buffer, uiBufSize);
428 }
429
430 inline static ssize_t ADDON_Write(const AddonInstance_VFSEntry* instance, void* context, const void* buffer, size_t uiBufSize)
431 {
432 return instance->toAddon.addonInstance->Write(context, buffer, uiBufSize);
433 }
434
435 inline static int64_t ADDON_Seek(const AddonInstance_VFSEntry* instance, void* context, int64_t position, int whence)
436 {
437 return instance->toAddon.addonInstance->Seek(context, position, whence);
438 }
439
440 inline static int ADDON_Truncate(const AddonInstance_VFSEntry* instance, void* context, int64_t size)
441 {
442 return instance->toAddon.addonInstance->Truncate(context, size);
443 }
444
445 inline static int64_t ADDON_GetLength(const AddonInstance_VFSEntry* instance, void* context)
446 {
447 return instance->toAddon.addonInstance->GetLength(context);
448 }
449
450 inline static int64_t ADDON_GetPosition(const AddonInstance_VFSEntry* instance, void* context)
451 {
452 return instance->toAddon.addonInstance->GetPosition(context);
453 }
454
455 inline static int ADDON_GetChunkSize(const AddonInstance_VFSEntry* instance, void* context)
456 {
457 return instance->toAddon.addonInstance->GetChunkSize(context);
458 }
459
460 inline static int ADDON_IoControl(const AddonInstance_VFSEntry* instance, void* context, XFILE::EIoControl request, void* param)
461 {
462 return instance->toAddon.addonInstance->IoControl(context, request, param);
463 }
464
465 inline static int ADDON_Stat(const AddonInstance_VFSEntry* instance, const VFSURL* url, struct __stat64* buffer)
466 {
467 return instance->toAddon.addonInstance->Stat(*url, buffer);
468 }
469
470 inline static bool ADDON_Close(const AddonInstance_VFSEntry* instance, void* context)
471 {
472 return instance->toAddon.addonInstance->Close(context);
473 }
474
475 inline static bool ADDON_Exists(const AddonInstance_VFSEntry* instance, const VFSURL* url)
476 {
477 return instance->toAddon.addonInstance->Exists(*url);
478 }
479
480 inline static void ADDON_ClearOutIdle(const AddonInstance_VFSEntry* instance)
481 {
482 return instance->toAddon.addonInstance->ClearOutIdle();
483 }
484
485 inline static void ADDON_DisconnectAll(const AddonInstance_VFSEntry* instance)
486 {
487 return instance->toAddon.addonInstance->DisconnectAll();
488 }
489
490 inline static bool ADDON_Delete(const AddonInstance_VFSEntry* instance, const VFSURL* url)
491 {
492 return instance->toAddon.addonInstance->Delete(*url);
493 }
494
495 inline static bool ADDON_Rename(const AddonInstance_VFSEntry* instance, const VFSURL* url, const VFSURL* url2)
496 {
497 return instance->toAddon.addonInstance->Rename(*url, *url2);
498 }
499
500 inline static bool ADDON_DirectoryExists(const AddonInstance_VFSEntry* instance, const VFSURL* url)
501 {
502 return instance->toAddon.addonInstance->DirectoryExists(*url);
503 }
504
505 inline static bool ADDON_RemoveDirectory(const AddonInstance_VFSEntry* instance, const VFSURL* url)
506 {
507 return instance->toAddon.addonInstance->RemoveDirectory(*url);
508 }
509
510 inline static bool ADDON_CreateDirectory(const AddonInstance_VFSEntry* instance, const VFSURL* url)
511 {
512 return instance->toAddon.addonInstance->CreateDirectory(*url);
513 }
514
515 inline static bool ADDON_GetDirectory(const AddonInstance_VFSEntry* instance,
516 const VFSURL* url,
517 VFSDirEntry** retEntries,
518 int* num_entries,
519 VFSGetDirectoryCallbacks* callbacks)
520 {
521 std::vector<kodi::vfs::CDirEntry> addonEntries;
522 bool ret = instance->toAddon.addonInstance->GetDirectory(*url, addonEntries, callbacks);
523 if (ret)
524 {
525 VFSDirEntry* entries = static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size()));
526 for (unsigned int i = 0; i < addonEntries.size(); ++i)
527 {
528 entries[i].label = strdup(addonEntries[i].Label().c_str());
529 entries[i].title = strdup(addonEntries[i].Title().c_str());
530 entries[i].path = strdup(addonEntries[i].Path().c_str());
531 entries[i].folder = addonEntries[i].IsFolder();
532 entries[i].size = addonEntries[i].Size();
533
534 entries[i].num_props = 0;
535 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
536 if (!props.empty())
537 {
538 entries[i].properties = static_cast<VFSProperty*>(malloc(sizeof(VFSProperty)*props.size()));
539 for (const auto& prop : props)
540 {
541 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
542 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
543 ++entries[i].num_props;
544 }
545 }
546 else
547 entries[i].properties = nullptr;
548 }
549 *retEntries = entries;
550 *num_entries = addonEntries.size();
551 }
552 return ret;
553 }
554
555 inline static void ADDON_FreeDirectory(const AddonInstance_VFSEntry* instance, VFSDirEntry* entries, int num_entries)
556 {
557 for (int i = 0; i < num_entries; ++i)
558 {
559 if (entries[i].properties)
560 {
561 for (unsigned int j = 0; j < entries[i].num_props; ++j)
562 {
563 free(entries[i].properties[j].name);
564 free(entries[i].properties[j].val);
565 }
566 free(entries[i].properties);
567 }
568 free(entries[i].label);
569 free(entries[i].title);
570 free(entries[i].path);
571 }
572 free(entries);
573 }
574
575 inline static bool ADDON_ContainsFiles(const AddonInstance_VFSEntry* instance,
576 const VFSURL* url,
577 VFSDirEntry** retEntries,
578 int* num_entries,
579 char* rootpath)
580 {
581 std::string cppRootPath;
582 std::vector<kodi::vfs::CDirEntry> addonEntries;
583 bool ret = instance->toAddon.addonInstance->ContainsFiles(*url, addonEntries, cppRootPath);
584 if (ret)
585 {
586 strncpy(rootpath, cppRootPath.c_str(), ADDON_STANDARD_STRING_LENGTH);
587
588 VFSDirEntry* entries = static_cast<VFSDirEntry*>(malloc(sizeof(VFSDirEntry) * addonEntries.size()));
589 for (unsigned int i = 0; i < addonEntries.size(); ++i)
590 {
591 entries[i].label = strdup(addonEntries[i].Label().c_str());
592 entries[i].title = strdup(addonEntries[i].Title().c_str());
593 entries[i].path = strdup(addonEntries[i].Path().c_str());
594 entries[i].folder = addonEntries[i].IsFolder();
595 entries[i].size = addonEntries[i].Size();
596
597 entries[i].num_props = 0;
598 const std::map<std::string, std::string>& props = addonEntries[i].GetProperties();
599 if (!props.empty())
600 {
601 entries[i].properties = static_cast<VFSProperty*>(malloc(sizeof(VFSProperty)*props.size()));
602 for (const auto& prop : props)
603 {
604 entries[i].properties[entries[i].num_props].name = strdup(prop.first.c_str());
605 entries[i].properties[entries[i].num_props].val = strdup(prop.second.c_str());
606 ++entries[i].num_props;
607 }
608 }
609 else
610 entries[i].properties = nullptr;
611 }
612 *retEntries = entries;
613 *num_entries = addonEntries.size();
614 }
615 return ret;
616 }
617
618 AddonInstance_VFSEntry* m_instanceData;
619 };
620
621} /* namespace addon */
622} /* namespace kodi */
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h
new file mode 100644
index 0000000..710fda0
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/VideoCodec.h
@@ -0,0 +1,256 @@
1/*
2 * Copyright (C) 2017 Team XBMC
3 * http://xbmc.org
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#pragma once
22
23#include "../AddonBase.h"
24#include "../StreamCrypto.h"
25#include "../StreamCodec.h"
26
27#ifdef BUILD_KODI_ADDON
28#include "../DVDDemuxPacket.h"
29#else
30#include "cores/VideoPlayer/DVDDemuxers/DVDDemuxPacket.h"
31#endif
32
33namespace kodi { namespace addon { class CInstanceVideoCodec; } }
34
35extern "C"
36{
37 enum VIDEOCODEC_FORMAT
38 {
39 UnknownVideoFormat = 0,
40 VideoFormatYV12,
41 VideoFormatI420,
42 MaxVideoFormats
43 };
44
45
46 struct VIDEOCODEC_INITDATA
47 {
48 enum Codec {
49 CodecUnknown = 0,
50 CodecVp8,
51 CodecH264,
52 CodecVp9
53 } codec;
54
55 STREAMCODEC_PROFILE codecProfile;
56
57 //UnknownVideoFormat is terminator
58 VIDEOCODEC_FORMAT *videoFormats;
59
60 uint32_t width, height;
61
62 const uint8_t *extraData;
63 unsigned int extraDataSize;
64
65 CRYPTO_INFO cryptoInfo;
66 };
67
68 struct VIDEOCODEC_PICTURE
69 {
70 enum VideoPlane {
71 YPlane = 0,
72 UPlane,
73 VPlane,
74 MaxPlanes = 3,
75 };
76
77 enum Flags : uint32_t {
78 FLAG_DROP,
79 FLAG_DRAIN
80 };
81
82 VIDEOCODEC_FORMAT videoFormat;
83 uint32_t flags;
84
85 uint32_t width, height;
86
87 uint8_t *decodedData;
88 size_t decodedDataSize;
89
90 uint32_t planeOffsets[VideoPlane::MaxPlanes];
91 uint32_t stride[VideoPlane::MaxPlanes];
92
93 int64_t pts;
94
95 void *buffer; //< will be passed in release_frame_buffer
96 };
97
98 enum VIDEOCODEC_RETVAL
99 {
100 VC_NONE = 0, //< noop
101 VC_ERROR, //< an error occured, no other messages will be returned
102 VC_BUFFER, //< the decoder needs more data
103 VC_PICTURE, //< the decoder got a picture
104 VC_EOF, //< the decoder signals EOF
105 };
106
107 // this are properties given to the addon on create
108 // at this time we have no parameters for the addon
109 typedef struct AddonProps_VideoCodec
110 {
111 int dummy;
112 } AddonProps_VideoCodec;
113
114 struct AddonInstance_VideoCodec;
115 typedef struct KodiToAddonFuncTable_VideoCodec
116 {
117 kodi::addon::CInstanceVideoCodec* addonInstance;
118
119 //! \brief Opens a codec
120 bool (__cdecl* open) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData);
121
122 //! \brief Reconfigures a codec
123 bool (__cdecl* reconfigure) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData);
124
125 //! \brief Feed codec if requested from GetPicture() (return VC_BUFFER)
126 bool (__cdecl* add_data) (const AddonInstance_VideoCodec* instance, const DemuxPacket *packet);
127
128 //! \brief Get a decoded picture / request new data
129 VIDEOCODEC_RETVAL (__cdecl* get_picture) (const AddonInstance_VideoCodec* instance, VIDEOCODEC_PICTURE *picture);
130
131 //! \brief Get the name of this video decoder
132 const char *(__cdecl* get_name) (const AddonInstance_VideoCodec* instance);
133
134 //! \brief Reset the codec
135 void (__cdecl* reset)(const AddonInstance_VideoCodec* instance);
136 } KodiToAddonFuncTable_VideoCodec;
137
138 typedef struct AddonToKodiFuncTable_VideoCodec
139 {
140 KODI_HANDLE kodiInstance;
141 bool(*get_frame_buffer)(void* kodiInstance, VIDEOCODEC_PICTURE *picture);
142 void(*release_frame_buffer)(void* kodiInstance, void *buffer);
143 } AddonToKodiFuncTable_VideoCodec;
144
145 typedef struct AddonInstance_VideoCodec
146 {
147 AddonProps_VideoCodec props;
148 AddonToKodiFuncTable_VideoCodec toKodi;
149 KodiToAddonFuncTable_VideoCodec toAddon;
150 } AddonInstance_VideoCodec;
151}
152
153namespace kodi
154{
155 namespace addon
156 {
157
158 class CInstanceVideoCodec : public IAddonInstance
159 {
160 public:
161 CInstanceVideoCodec(KODI_HANDLE instance)
162 : IAddonInstance(ADDON_INSTANCE_VIDEOCODEC)
163 {
164 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
165 throw std::logic_error("kodi::addon::CInstanceVideoCodec: Creation of multiple together with single instance way is not allowed!");
166
167 SetAddonStruct(instance);
168 }
169
170 ~CInstanceVideoCodec() override = default;
171
172 //! \copydoc CInstanceVideoCodec::Open
173 virtual bool Open(VIDEOCODEC_INITDATA &initData) { return false; };
174
175 //! \copydoc CInstanceVideoCodec::Reconfigure
176 virtual bool Reconfigure(VIDEOCODEC_INITDATA &initData) { return false; };
177
178 //! \copydoc CInstanceVideoCodec::AddData
179 virtual bool AddData(const DemuxPacket &packet) { return false; };
180
181 //! \copydoc CInstanceVideoCodec::GetPicture
182 virtual VIDEOCODEC_RETVAL GetPicture(VIDEOCODEC_PICTURE &picture) { return VC_ERROR; };
183
184 //! \copydoc CInstanceVideoCodec::GetName
185 virtual const char *GetName() { return nullptr; };
186
187 //! \copydoc CInstanceVideoCodec::Reset
188 virtual void Reset() {};
189
190 /*!
191 * @brief AddonToKodi interface
192 */
193
194 //! \copydoc CInstanceVideoCodec::GetFrameBuffer
195 bool GetFrameBuffer(VIDEOCODEC_PICTURE &picture)
196 {
197 return m_instanceData->toKodi.get_frame_buffer(m_instanceData->toKodi.kodiInstance, &picture);
198 }
199
200 //! \copydoc CInstanceVideoCodec::ReleaseFrameBuffer
201 void ReleaseFrameBuffer(void *buffer)
202 {
203 return m_instanceData->toKodi.release_frame_buffer(m_instanceData->toKodi.kodiInstance, buffer);
204 }
205
206 private:
207 void SetAddonStruct(KODI_HANDLE instance)
208 {
209 if (instance == nullptr)
210 throw std::logic_error("kodi::addon::CInstanceVideoCodec: Creation with empty addon structure not allowed, table must be given from Kodi!");
211
212 m_instanceData = static_cast<AddonInstance_VideoCodec*>(instance);
213
214 m_instanceData->toAddon.addonInstance = this;
215 m_instanceData->toAddon.open = ADDON_Open;
216 m_instanceData->toAddon.reconfigure = ADDON_Reconfigure;
217 m_instanceData->toAddon.add_data = ADDON_AddData;
218 m_instanceData->toAddon.get_picture = ADDON_GetPicture;
219 m_instanceData->toAddon.get_name = ADDON_GetName;
220 m_instanceData->toAddon.reset = ADDON_Reset;
221 }
222
223 inline static bool ADDON_Open(const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData)
224 {
225 return instance->toAddon.addonInstance->Open(*initData);
226 }
227
228 inline static bool ADDON_Reconfigure(const AddonInstance_VideoCodec* instance, VIDEOCODEC_INITDATA *initData)
229 {
230 return instance->toAddon.addonInstance->Reconfigure(*initData);
231 }
232
233 inline static bool ADDON_AddData(const AddonInstance_VideoCodec* instance, const DemuxPacket *packet)
234 {
235 return instance->toAddon.addonInstance->AddData(*packet);
236 }
237
238 inline static VIDEOCODEC_RETVAL ADDON_GetPicture(const AddonInstance_VideoCodec* instance, VIDEOCODEC_PICTURE *picture)
239 {
240 return instance->toAddon.addonInstance->GetPicture(*picture);
241 }
242
243 inline static const char *ADDON_GetName(const AddonInstance_VideoCodec* instance)
244 {
245 return instance->toAddon.addonInstance->GetName();
246 }
247
248 inline static void ADDON_Reset(const AddonInstance_VideoCodec* instance)
249 {
250 return instance->toAddon.addonInstance->Reset();
251 }
252
253 AddonInstance_VideoCodec* m_instanceData;
254 };
255 } // namespace addon
256} // namespace kodi
diff --git a/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h
new file mode 100644
index 0000000..b1ded64
--- /dev/null
+++ b/xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance/Visualization.h
@@ -0,0 +1,766 @@
1#pragma once
2/*
3 * Copyright (C) 2005-2017 Team Kodi
4 * http://kodi.tv
5 *
6 * This Program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * This Program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Kodi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 */
21
22/*
23 * Parts with a comment named "internal" are only used inside header and not
24 * used or accessed direct during add-on development!
25 */
26
27#include "../AddonBase.h"
28
29namespace kodi { namespace addon { class CInstanceVisualization; }}
30
31extern "C"
32{
33
34struct AddonInstance_Visualization;
35
36typedef enum VIS_ACTION : unsigned int /* internal */
37{
38 VIS_ACTION_NONE = 0,
39 VIS_ACTION_NEXT_PRESET,
40 VIS_ACTION_PREV_PRESET,
41 VIS_ACTION_LOAD_PRESET,
42 VIS_ACTION_RANDOM_PRESET,
43 VIS_ACTION_LOCK_PRESET,
44 VIS_ACTION_RATE_PRESET_PLUS,
45 VIS_ACTION_RATE_PRESET_MINUS,
46 VIS_ACTION_UPDATE_ALBUMART,
47 VIS_ACTION_UPDATE_TRACK
48} VIS_ACTION;
49
50struct VIS_INFO /* internal */
51{
52 bool bWantsFreq;
53 int iSyncDelay;
54};
55
56typedef struct AddonProps_Visualization /* internal */
57{
58 void *device;
59 int x;
60 int y;
61 int width;
62 int height;
63 float pixelRatio;
64 const char *name;
65 const char *presets;
66 const char *profile;
67} AddonProps_Visualization;
68
69typedef struct AddonToKodiFuncTable_Visualization /* internal */
70{
71 KODI_HANDLE kodiInstance;
72 void (__cdecl* transfer_preset) (void* kodiInstance, const char* preset);
73} AddonToKodiFuncTable_Visualization;
74
75typedef struct KodiToAddonFuncTable_Visualization /* internal */
76{
77 kodi::addon::CInstanceVisualization* addonInstance;
78 bool (__cdecl* start)(const AddonInstance_Visualization* instance, int channels, int samples_per_sec, int bits_per_sample, const char* song_name);
79 void (__cdecl* stop)(const AddonInstance_Visualization* instance);
80 void (__cdecl* audio_data)(const AddonInstance_Visualization* instance, const float* audio_data, int audio_data_length, float *freq_data, int freq_data_length);
81 bool (__cdecl* is_dirty)(const AddonInstance_Visualization* instance);
82 void (__cdecl* render)(const AddonInstance_Visualization* instance);
83 void (__cdecl* get_info)(const AddonInstance_Visualization* instance, VIS_INFO *info);
84 bool (__cdecl* on_action)(const AddonInstance_Visualization* instance, VIS_ACTION action, const void *param);
85 unsigned int (__cdecl *get_presets)(const AddonInstance_Visualization* instance);
86 int (__cdecl *get_active_preset)(const AddonInstance_Visualization* instance);
87 bool (__cdecl* is_locked)(const AddonInstance_Visualization* instance);
88} KodiToAddonFuncTable_Visualization;
89
90typedef struct AddonInstance_Visualization /* internal */
91{
92 AddonProps_Visualization props;
93 AddonToKodiFuncTable_Visualization toKodi;
94 KodiToAddonFuncTable_Visualization toAddon;
95} AddonInstance_Visualization;
96
97//============================================================================
98/// \defgroup cpp_kodi_addon_visualization_VisTrack class VisTrack
99/// \ingroup cpp_kodi_addon_visualization
100/// @brief **Visualization track information structure**
101///
102/// Called from kodi::addon::CInstanceVisualization::UpdateTrack() with the
103/// information of the currently-playing song.
104///
105//@{
106struct VisTrack
107{
108 /// @brief Title of the current song.
109 const char *title;
110
111 /// @brief Artist names, as a single string
112 const char *artist;
113
114 /// @brief Album that the current song is from.
115 const char *album;
116
117 /// @brief Album artist names, as a single string
118 const char *albumArtist;
119
120 /// @brief The genre name from the music tag, if present.
121 const char *genre;
122
123 /// @brief Comment of the current song stored in the ID tag info.
124 const char *comment;
125
126 /// @brief Lyrics of the current song, if available.
127 const char *lyrics;
128
129 const char *reserved1;
130 const char *reserved2;
131
132 /// @brief Track number of the current song.
133 int trackNumber;
134
135 /// @brief Disc number of the current song stored in the ID tag info.
136 int discNumber;
137
138 /// @brief Duration of the current song, in seconds.
139 int duration;
140
141 /// @brief Year that the current song was released.
142 int year;
143
144 /// @brief The user-defined rating of the current song.
145 int rating;
146
147 int reserved3;
148 int reserved4;
149};
150//@}
151//----------------------------------------------------------------------------
152
153} /* extern "C" */
154
155namespace kodi
156{
157namespace addon
158{
159
160 //============================================================================
161 ///
162 /// \addtogroup cpp_kodi_addon_visualization
163 /// @brief \cpp_class{ kodi::addon::CInstanceVisualization }
164 /// **Visualization add-on instance**
165 ///
166 /// [Music visualization](https://en.wikipedia.org/wiki/Music_visualization),
167 /// or music visualisation, is a feature in Kodi that generates animated
168 /// imagery based on a piece of music. The imagery is usually generated and
169 /// rendered in real time synchronized to the music.
170 ///
171 /// Visualization techniques range from simple ones (e.g., a simulation of an
172 /// oscilloscope display) to elaborate ones, which often include a plurality
173 /// of composited effects. The changes in the music's loudness and frequency
174 /// spectrum are among the properties used as input to the visualization.
175 ///
176 /// Include the header \ref Visualization.h "#include <kodi/addon-instance/Visualization.h>"
177 /// to use this class.
178 ///
179 /// This interface allows the creation of visualizations for Kodi, based upon
180 /// **DirectX** or/and **OpenGL** rendering with `C++` code.
181 ///
182 /// Additionally, there are several \ref cpp_kodi_addon_visualization_CB "other functions"
183 /// available in which the child class can ask about the current hardware,
184 /// including the device, display and several other parts.
185 ///
186 /// --------------------------------------------------------------------------
187 ///
188 ///
189 /// **Here is an example of the minimum required code to start a visualization:**
190 /// ~~~~~~~~~~~~~{.cpp}
191 /// #include <kodi/addon-instance/Visualization.h>
192 ///
193 /// class CMyVisualization : public kodi::addon::CAddonBase,
194 /// public kodi::addon::CInstanceVisualization
195 /// {
196 /// public:
197 /// CMyVisualization();
198 ///
199 /// bool Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName) override;
200 /// void AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength) override;
201 /// void Render() override;
202 /// };
203 ///
204 /// CMyVisualization::CMyVisualization()
205 /// {
206 /// ...
207 /// }
208 ///
209 /// bool CMyVisualization::Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName)
210 /// {
211 /// ...
212 /// return true;
213 /// }
214 ///
215 /// void CMyVisualization::AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength)
216 /// {
217 /// ...
218 /// }
219 ///
220 /// void CMyVisualization::Render()
221 /// {
222 /// ...
223 /// }
224 ///
225 /// ADDONCREATOR(CMyVisualization)
226 /// ~~~~~~~~~~~~~
227 ///
228 ///
229 /// --------------------------------------------------------------------------
230 ///
231 ///
232 /// **Here is another example where the visualization is used together with
233 /// other instance types:**
234 ///
235 /// ~~~~~~~~~~~~~{.cpp}
236 /// #include <kodi/addon-instance/Visualization.h>
237 ///
238 /// class CMyVisualization : public ::kodi::addon::CInstanceVisualization
239 /// {
240 /// public:
241 /// CMyVisualization(KODI_HANDLE instance);
242 ///
243 /// bool Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName) override;
244 /// void AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength) override;
245 /// void Render() override;
246 /// };
247 ///
248 /// CMyVisualization::CMyVisualization(KODI_HANDLE instance)
249 /// : CInstanceVisualization(instance)
250 /// {
251 /// ...
252 /// }
253 ///
254 /// bool CMyVisualization::Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName)
255 /// {
256 /// ...
257 /// return true;
258 /// }
259 ///
260 /// void CMyVisualization::AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength)
261 /// {
262 /// ...
263 /// }
264 ///
265 /// void CMyVisualization::Render()
266 /// {
267 /// ...
268 /// }
269 ///
270 ///
271 /// /*----------------------------------------------------------------------*/
272 ///
273 /// class CMyAddon : public ::kodi::addon::CAddonBase
274 /// {
275 /// public:
276 /// CMyAddon() { }
277 /// ADDON_STATUS CreateInstance(int instanceType,
278 /// std::string instanceID,
279 /// KODI_HANDLE instance,
280 /// KODI_HANDLE& addonInstance) override;
281 /// };
282 ///
283 /// /* If you use only one instance in your add-on, can be instanceType and
284 /// * instanceID ignored */
285 /// ADDON_STATUS CMyAddon::CreateInstance(int instanceType,
286 /// std::string instanceID,
287 /// KODI_HANDLE instance,
288 /// KODI_HANDLE& addonInstance)
289 /// {
290 /// if (instanceType == ADDON_INSTANCE_VISUALIZATION)
291 /// {
292 /// kodi::Log(ADDON_LOG_NOTICE, "Creating my Visualization");
293 /// addonInstance = new CMyVisualization(instance);
294 /// return ADDON_STATUS_OK;
295 /// }
296 /// else if (...)
297 /// {
298 /// ...
299 /// }
300 /// return ADDON_STATUS_UNKNOWN;
301 /// }
302 ///
303 /// ADDONCREATOR(CMyAddon)
304 /// ~~~~~~~~~~~~~
305 ///
306 /// The destruction of the example class `CMyVisualization` is called from
307 /// Kodi's header. Manually deleting the add-on instance is not required.
308 ///
309 //----------------------------------------------------------------------------
310 class CInstanceVisualization : public IAddonInstance
311 {
312 public:
313 //==========================================================================
314 ///
315 /// @ingroup cpp_kodi_addon_visualization
316 /// @brief Visualization class constructor
317 ///
318 /// Used by an add-on that only supports visualizations.
319 ///
320 CInstanceVisualization()
321 : IAddonInstance(ADDON_INSTANCE_VISUALIZATION),
322 m_presetLockedByUser(false)
323 {
324 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
325 throw std::logic_error("kodi::addon::CInstanceVisualization: Cannot create multiple instances of add-on.");
326
327 SetAddonStruct(CAddonBase::m_interface->firstKodiInstance);
328 CAddonBase::m_interface->globalSingleInstance = this;
329 }
330 //--------------------------------------------------------------------------
331
332 //==========================================================================
333 ///
334 /// @ingroup cpp_kodi_addon_visualization
335 /// @brief Visualization class constructor used to support multiple instance
336 /// types
337 ///
338 /// @param[in] instance The instance value given to
339 /// <b>`kodi::addon::CAddonBase::CreateInstance(...)`</b>.
340 ///
341 /// @warning Only use `instance` from the CreateInstance call
342 ///
343 CInstanceVisualization(KODI_HANDLE instance)
344 : IAddonInstance(ADDON_INSTANCE_VISUALIZATION),
345 m_presetLockedByUser(false)
346 {
347 if (CAddonBase::m_interface->globalSingleInstance != nullptr)
348 throw std::logic_error("kodi::addon::CInstanceVisualization: Creation of multiple together with single instance way is not allowed!");
349
350 SetAddonStruct(instance);
351 }
352 //--------------------------------------------------------------------------
353
354 //==========================================================================
355 ///
356 /// @ingroup cpp_kodi_addon_visualization
357 /// @brief Destructor
358 ///
359 ~CInstanceVisualization() override = default;
360 //--------------------------------------------------------------------------
361
362 //==========================================================================
363 ///
364 /// @ingroup cpp_kodi_addon_visualization
365 /// @brief Used to notify the visualization that a new song has been started
366 ///
367 /// @param[in] channels Number of channels in the stream
368 /// @param[in] samplesPerSec Samples per second of stream
369 /// @param[in] bitsPerSample Number of bits in one sample
370 /// @param[in] songName The name of the currently-playing song
371 /// @return true if start successful done
372 ///
373 virtual bool Start(int channels, int samplesPerSec, int bitsPerSample, std::string songName) { return true; }
374 //--------------------------------------------------------------------------
375
376 //==========================================================================
377 ///
378 /// @ingroup cpp_kodi_addon_visualization
379 /// @brief Used to inform the visualization that the rendering control was
380 /// stopped
381 ///
382 virtual void Stop() {}
383 //--------------------------------------------------------------------------
384
385 //==========================================================================
386 ///
387 /// @ingroup cpp_kodi_addon_visualization
388 /// @brief Pass audio data to the visualization
389 ///
390 /// @param[in] audioData The raw audio data
391 /// @param[in] audioDataLength Length of the audioData array
392 /// @param[in] freqData The [FFT](https://en.wikipedia.org/wiki/Fast_Fourier_transform)
393 /// of the audio data
394 /// @param[in] freqDataLength Length of frequency data array
395 ///
396 /// Values **freqData** and **freqDataLength** are used if GetInfo() returns
397 /// true for the `wantsFreq` parameter. Otherwise, **freqData** is set to
398 /// `nullptr` and **freqDataLength** is `0`.
399 ///
400 virtual void AudioData(const float* audioData, int audioDataLength, float* freqData, int freqDataLength) {}
401 //--------------------------------------------------------------------------
402
403 //==========================================================================
404 ///
405 /// @ingroup cpp_kodi_addon_visualization
406 /// @brief Used to inform Kodi that the rendered region is dirty and need an
407 /// update
408 ///
409 /// @return True if dirty
410 ///
411 virtual bool IsDirty() { return true; }
412 //--------------------------------------------------------------------------
413
414 //==========================================================================
415 ///
416 /// @ingroup cpp_kodi_addon_visualization
417 /// @brief Used to indicate when the add-on should render
418 ///
419 virtual void Render() {}
420 //--------------------------------------------------------------------------
421
422 //==========================================================================
423 ///
424 /// @ingroup cpp_kodi_addon_visualization
425 /// @brief Used to get the number of buffers from the current visualization
426 ///
427 /// @param[out] wantsFreq Indicates whether the add-on wants FFT
428 /// data. If set to true, the **freqData**
429 /// and **freqDataLength** parameters of
430 /// AudioData() are used
431 /// @param[out] syncDelay The number of buffers to delay before
432 /// calling AudioData()
433 ///
434 /// @note If this function is not implemented, it will default to
435 /// `wantsFreq` = false and `syncDelay` = 0.
436 ///
437 virtual void GetInfo(bool& wantsFreq, int& syncDelay) { wantsFreq = false; syncDelay = 0; }
438 //--------------------------------------------------------------------------
439
440 //==========================================================================
441 ///
442 /// @ingroup cpp_kodi_addon_visualization
443 /// @brief Used to get a list of visualization presets the user can select
444 /// from
445 ///
446 /// @param[out] presets The vector list containing the names of
447 /// presets that the user can select
448 /// @return Return true if successful, or false if
449 /// there are no presets to choose from
450 ///
451 virtual bool GetPresets(std::vector<std::string>& presets) { return false; }
452 //--------------------------------------------------------------------------
453
454 //==========================================================================
455 ///
456 /// @ingroup cpp_kodi_addon_visualization
457 /// @brief Get the index of the current preset
458 ///
459 /// @return Index number of the current preset
460 ///
461 virtual int GetActivePreset() { return -1; }
462 //--------------------------------------------------------------------------
463
464 //==========================================================================
465 ///
466 /// @ingroup cpp_kodi_addon_visualization
467 /// @brief Check if the add-on is locked to the current preset
468 ///
469 /// @return True if locked to the current preset
470 ///
471 virtual bool IsLocked() { return false; }
472 //--------------------------------------------------------------------------
473
474 //==========================================================================
475 ///
476 /// @ingroup cpp_kodi_addon_visualization
477 /// @brief Load the previous visualization preset
478 ///
479 /// @return Return true if the previous preset was loaded
480 virtual bool PrevPreset() { return false; }
481 //--------------------------------------------------------------------------
482
483 //==========================================================================
484 ///
485 /// @ingroup cpp_kodi_addon_visualization
486 /// @brief Load the next visualization preset
487 ///
488 /// @return Return true if the next preset was loaded
489 virtual bool NextPreset() { return false; }
490 //--------------------------------------------------------------------------
491
492 //==========================================================================
493 ///
494 /// @ingroup cpp_kodi_addon_visualization
495 /// @brief Load a visualization preset
496 ///
497 /// This function is called after a new preset is selected.
498 ///
499 /// @param[in] select Preset index to use
500 /// @return Return true if the preset is loaded
501 virtual bool LoadPreset(int select) { return false; }
502 //--------------------------------------------------------------------------
503
504 //==========================================================================
505 ///
506 /// @ingroup cpp_kodi_addon_visualization
507 /// @brief Switch to a new random preset
508 ///
509 /// @return Return true if a random preset was loaded
510 virtual bool RandomPreset() { return false; }
511 //--------------------------------------------------------------------------
512
513 //==========================================================================
514 ///
515 /// @ingroup cpp_kodi_addon_visualization
516 /// @brief Lock the current visualization preset, preventing it from changing
517 ///
518 /// @param[in] lockUnlock If set to true, the preset should be locked
519 /// @return Return true if the current preset is locked
520 virtual bool LockPreset(bool lockUnlock) { return false; }
521 //--------------------------------------------------------------------------
522
523 //==========================================================================
524 ///
525 /// @ingroup cpp_kodi_addon_visualization
526 /// @brief Used to increase/decrease the visualization preset rating
527 ///
528 /// @param[in] plusMinus If set to true the rating is increased, otherwise
529 /// decreased
530 /// @return Return true if the rating is modified
531 virtual bool RatePreset(bool plusMinus) { return false; }
532 //--------------------------------------------------------------------------
533
534 //==========================================================================
535 ///
536 /// @ingroup cpp_kodi_addon_visualization
537 /// @brief Inform the visualization of the current album art image
538 ///
539 /// @param[in] albumart Path to the current album art image
540 /// @return Return true if the image is used
541 virtual bool UpdateAlbumart(std::string albumart) { return false; }
542 //--------------------------------------------------------------------------
543
544 //==========================================================================
545 ///
546 /// @ingroup cpp_kodi_addon_visualization
547 /// @brief Inform the visualization of the current track's tag information
548 ///
549 /// @param[in] track Visualization track information structure
550 /// @return Return true if the track information is used
551 virtual bool UpdateTrack(const VisTrack &track) { return false; }
552
553 //==========================================================================
554 ///
555 /// \defgroup cpp_kodi_addon_visualization_CB Information functions
556 /// \ingroup cpp_kodi_addon_visualization
557 /// @brief **To get info about the device, display and several other parts**
558 ///
559 //@{
560
561 //==========================================================================
562 ///
563 /// @ingroup cpp_kodi_addon_visualization_CB
564 /// @brief Device that represents the display adapter
565 ///
566 /// @return A pointer to the used device
567 ///
568 /// @note This is only available on **DirectX**, It us unused (`nullptr`) on
569 /// **OpenGL**
570 ///
571 inline void* Device() { return m_instanceData->props.device; }
572 //--------------------------------------------------------------------------
573
574 //==========================================================================
575 ///
576 /// @ingroup cpp_kodi_addon_visualization_CB
577 /// @brief Returns the X position of the rendering window
578 ///
579 /// @return The X position, in pixels
580 ///
581 inline int X() { return m_instanceData->props.x; }
582 //--------------------------------------------------------------------------
583
584 //==========================================================================
585 ///
586 /// @ingroup cpp_kodi_addon_visualization_CB
587 /// @brief Returns the Y position of the rendering window
588 ///
589 /// @return The Y position, in pixels
590 ///
591 inline int Y() { return m_instanceData->props.y; }
592 //--------------------------------------------------------------------------
593
594 //==========================================================================
595 ///
596 /// @ingroup cpp_kodi_addon_visualization_CB
597 /// @brief Returns the width of the rendering window
598 ///
599 /// @return The width, in pixels
600 ///
601 inline int Width() { return m_instanceData->props.width; }
602 //--------------------------------------------------------------------------
603
604 //==========================================================================
605 ///
606 /// @ingroup cpp_kodi_addon_visualization_CB
607 /// @brief Returns the height of the rendering window
608 ///
609 /// @return The height, in pixels
610 ///
611 inline int Height() { return m_instanceData->props.height; }
612 //--------------------------------------------------------------------------
613
614 //==========================================================================
615 ///
616 /// @ingroup cpp_kodi_addon_visualization_CB
617 /// @brief Pixel aspect ratio (often abbreviated PAR) is a ratio that
618 /// describes how the width of a pixel compares to the height of that pixel.
619 ///
620 /// @return The pixel aspect ratio used by the display
621 ///
622 inline float PixelRatio() { return m_instanceData->props.pixelRatio; }
623 //--------------------------------------------------------------------------
624
625 //==========================================================================
626 ///
627 /// @ingroup cpp_kodi_addon_visualization_CB
628 /// @brief Used to get the name of the add-on defined in `addon.xml`
629 ///
630 /// @return The add-on name
631 ///
632 inline std::string Name() { return m_instanceData->props.name; }
633 //--------------------------------------------------------------------------
634
635 //==========================================================================
636 ///
637 /// @ingroup cpp_kodi_addon_visualization_CB
638 /// @brief Used to get the full path where the add-on is installed
639 ///
640 /// @return The add-on installation path
641 ///
642 inline std::string Presets() { return m_instanceData->props.presets; }
643 //--------------------------------------------------------------------------
644
645 //==========================================================================
646 ///
647 /// @ingroup cpp_kodi_addon_visualization_CB
648 /// @brief Used to get the full path to the add-on's user profile
649 ///
650 /// @note The trailing folder (consisting of the add-on's ID) is not created
651 /// by default. If it is needed, you must call kodi::vfs::CreateDirectory()
652 /// to create the folder.
653 ///
654 /// @return Path to the user profile
655 ///
656 inline std::string Profile() { return m_instanceData->props.profile; }
657 //--------------------------------------------------------------------------
658 //@}
659
660 private:
661 void SetAddonStruct(KODI_HANDLE instance)
662 {
663 if (instance == nullptr)
664 throw std::logic_error("kodi::addon::CInstanceVisualization: Null pointer instance passed.");
665
666 m_instanceData = static_cast<AddonInstance_Visualization*>(instance);
667 m_instanceData->toAddon.addonInstance = this;
668 m_instanceData->toAddon.start = ADDON_Start;
669 m_instanceData->toAddon.stop = ADDON_Stop;
670 m_instanceData->toAddon.audio_data = ADDON_AudioData;
671 m_instanceData->toAddon.render = ADDON_Render;
672 m_instanceData->toAddon.get_info = ADDON_GetInfo;
673 m_instanceData->toAddon.on_action = ADDON_OnAction;
674 m_instanceData->toAddon.get_presets = ADDON_GetPresets;
675 m_instanceData->toAddon.get_active_preset = ADDON_GetActivePreset;
676 m_instanceData->toAddon.is_locked = ADDON_IsLocked;
677 }
678
679 inline static bool ADDON_Start(const AddonInstance_Visualization* addon, int channels, int samplesPerSec, int bitsPerSample, const char* songName)
680 {
681 return addon->toAddon.addonInstance->Start(channels, samplesPerSec, bitsPerSample, songName);
682 }
683
684 inline static void ADDON_Stop(const AddonInstance_Visualization* addon)
685 {
686 addon->toAddon.addonInstance->Stop();
687 }
688
689 inline static void ADDON_AudioData(const AddonInstance_Visualization* addon, const float* audioData, int audioDataLength, float *freqData, int freqDataLength)
690 {
691 addon->toAddon.addonInstance->AudioData(audioData, audioDataLength, freqData, freqDataLength);
692 }
693
694 inline static bool ADDON_IsDirty(const AddonInstance_Visualization* addon)
695 {
696 return addon->toAddon.addonInstance->IsDirty();
697 }
698
699 inline static void ADDON_Render(const AddonInstance_Visualization* addon)
700 {
701 addon->toAddon.addonInstance->Render();
702 }
703
704 inline static void ADDON_GetInfo(const AddonInstance_Visualization* addon, VIS_INFO *info)
705 {
706 addon->toAddon.addonInstance->GetInfo(info->bWantsFreq, info->iSyncDelay);
707 }
708
709 inline static bool ADDON_OnAction(const AddonInstance_Visualization* addon, VIS_ACTION action, const void *param)
710 {
711 switch (action)
712 {
713 case VIS_ACTION_NEXT_PRESET:
714 return addon->toAddon.addonInstance->NextPreset();
715 case VIS_ACTION_PREV_PRESET:
716 return addon->toAddon.addonInstance->PrevPreset();
717 case VIS_ACTION_LOAD_PRESET:
718 return addon->toAddon.addonInstance->LoadPreset(*static_cast<const int*>(param));
719 case VIS_ACTION_RANDOM_PRESET:
720 return addon->toAddon.addonInstance->RandomPreset();
721 case VIS_ACTION_LOCK_PRESET:
722 addon->toAddon.addonInstance->m_presetLockedByUser = !addon->toAddon.addonInstance->m_presetLockedByUser;
723 return addon->toAddon.addonInstance->LockPreset(addon->toAddon.addonInstance->m_presetLockedByUser);
724 case VIS_ACTION_RATE_PRESET_PLUS:
725 return addon->toAddon.addonInstance->RatePreset(true);
726 case VIS_ACTION_RATE_PRESET_MINUS:
727 return addon->toAddon.addonInstance->RatePreset(false);
728 case VIS_ACTION_UPDATE_ALBUMART:
729 return addon->toAddon.addonInstance->UpdateAlbumart(static_cast<const char*>(param));
730 case VIS_ACTION_UPDATE_TRACK:
731 return addon->toAddon.addonInstance->UpdateTrack(*static_cast<const VisTrack*>(param));
732 case VIS_ACTION_NONE:
733 default:
734 break;
735 }
736 return false;
737 }
738
739 inline static unsigned int ADDON_GetPresets(const AddonInstance_Visualization* addon)
740 {
741 std::vector<std::string> presets;
742 if (addon->toAddon.addonInstance->GetPresets(presets))
743 {
744 for (auto it : presets)
745 addon->toAddon.addonInstance->m_instanceData->toKodi.transfer_preset(addon->toKodi.kodiInstance, it.c_str());
746 }
747
748 return presets.size();
749 }
750
751 inline static int ADDON_GetActivePreset(const AddonInstance_Visualization* addon)
752 {
753 return addon->toAddon.addonInstance->GetActivePreset();
754 }
755
756 inline static bool ADDON_IsLocked(const AddonInstance_Visualization* addon)
757 {
758 return addon->toAddon.addonInstance->IsLocked();
759 }
760
761 bool m_presetLockedByUser;
762 AddonInstance_Visualization* m_instanceData;
763 };
764
765} /* namespace addon */
766} /* namespace kodi */