diff options
| author | manuel <manuel@mausz.at> | 2017-07-23 16:59:43 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2017-07-23 16:59:43 +0200 |
| commit | 4c3251ec645c8b71820dab7e51e612e5919d4e75 (patch) | |
| tree | 9533268a93e58fc2e16de1b8ee3fafe3784e5225 /xbmc/addons/kodi-addon-dev-kit/include/kodi/addon-instance | |
| parent | f44ecaa4f27e7538ddcad66d40e543bffa2d2d86 (diff) | |
| download | kodi-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')
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 | |||
| 90 | namespace kodi { namespace addon { class CInstanceAudioDSP; }} | ||
| 91 | |||
| 92 | extern "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 | |||
| 556 | namespace kodi { | ||
| 557 | namespace 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 | |||
| 30 | namespace kodi { namespace addon { class CInstanceAudioDecoder; }} | ||
| 31 | |||
| 32 | extern "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 | |||
| 72 | namespace kodi | ||
| 73 | { | ||
| 74 | namespace 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 | |||
| 24 | namespace kodi { namespace addon { class CInstanceAudioEncoder; }} | ||
| 25 | |||
| 26 | extern "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 | |||
| 64 | namespace kodi | ||
| 65 | { | ||
| 66 | namespace 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 | |||
| 24 | namespace kodi { namespace addon { class CInstanceImageDecoder; }} | ||
| 25 | |||
| 26 | extern "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 | |||
| 62 | typedef 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 | |||
| 70 | namespace kodi | ||
| 71 | { | ||
| 72 | namespace 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 | |||
| 37 | namespace kodi { namespace addon { class CInstanceInputStream; }} | ||
| 38 | |||
| 39 | extern "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 | |||
| 213 | namespace kodi | ||
| 214 | { | ||
| 215 | namespace 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 | |||
| 24 | namespace 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 | |||
| 32 | extern "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 | |||
| 301 | namespace kodi | ||
| 302 | { | ||
| 303 | namespace 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 | |||
| 33 | namespace kodi | ||
| 34 | { | ||
| 35 | namespace 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 | ||
| 29 | struct AddonInstance_Screensaver; | 29 | struct AddonInstance_Screensaver; |
| 30 | 30 | ||
| 31 | /*! | ||
| 32 | * @brief Screensaver properties | ||
| 33 | * | ||
| 34 | * Not to be used outside this header. | ||
| 35 | */ | ||
| 31 | typedef struct AddonProps_Screensaver | 36 | typedef 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 | */ | ||
| 44 | typedef struct AddonToKodiFuncTable_Screensaver | 54 | typedef 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 | */ | ||
| 49 | typedef struct KodiToAddonFuncTable_Screensaver | 64 | typedef 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 | */ | ||
| 57 | typedef struct AddonInstance_Screensaver | 77 | typedef struct AddonInstance_Screensaver |
| 58 | { | 78 | { |
| 59 | AddonProps_Screensaver props; | 79 | AddonProps_Screensaver props; |
| @@ -68,9 +88,157 @@ namespace kodi | |||
| 68 | namespace addon | 88 | namespace 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 | |||
| 31 | namespace kodi { namespace addon { class CInstanceVFS; }} | ||
| 32 | |||
| 33 | extern "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 | |||
| 115 | namespace kodi | ||
| 116 | { | ||
| 117 | namespace 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 | |||
| 33 | namespace kodi { namespace addon { class CInstanceVideoCodec; } } | ||
| 34 | |||
| 35 | extern "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 | |||
| 153 | namespace 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 | |||
| 29 | namespace kodi { namespace addon { class CInstanceVisualization; }} | ||
| 30 | |||
| 31 | extern "C" | ||
| 32 | { | ||
| 33 | |||
| 34 | struct AddonInstance_Visualization; | ||
| 35 | |||
| 36 | typedef 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 | |||
| 50 | struct VIS_INFO /* internal */ | ||
| 51 | { | ||
| 52 | bool bWantsFreq; | ||
| 53 | int iSyncDelay; | ||
| 54 | }; | ||
| 55 | |||
| 56 | typedef 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 | |||
| 69 | typedef struct AddonToKodiFuncTable_Visualization /* internal */ | ||
| 70 | { | ||
| 71 | KODI_HANDLE kodiInstance; | ||
| 72 | void (__cdecl* transfer_preset) (void* kodiInstance, const char* preset); | ||
| 73 | } AddonToKodiFuncTable_Visualization; | ||
| 74 | |||
| 75 | typedef 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 | |||
| 90 | typedef 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 | //@{ | ||
| 106 | struct 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 | |||
| 155 | namespace kodi | ||
| 156 | { | ||
| 157 | namespace 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 */ | ||
