summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/kodi-dev-kit/include/kodi/addon-instance/AudioEncoder.h
blob: 9a869c170590e1fc5d7089dc690430ce58704396 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "../AddonBase.h"
#include "../c-api/addon-instance/audio_encoder.h"

#ifdef __cplusplus
namespace kodi
{
namespace addon
{

//==============================================================================
/// @addtogroup cpp_kodi_addon_audioencoder
/// @brief \cpp_class{ kodi::addon::CInstanceAudioEncoder }
/// **Audio encoder add-on instance.**\n
/// For audio encoders as binary add-ons. This class implements a way to handle
/// the encode of given stream to a new format.
///
/// The addon.xml defines the capabilities of this add-on.
///
///
/// ----------------------------------------------------------------------------
///
/// **Here's an example on addon.xml:**
/// ~~~~~~~~~~~~~{.xml}
///   <extension
///     point="kodi.audioencoder"
///     extension=".flac"
///     library_@PLATFORM@="@LIBRARY_FILENAME@"/>
/// ~~~~~~~~~~~~~
///
/// Description to audio encoder related addon.xml values:
/// | Name                          | Description
/// |:------------------------------|----------------------------------------
/// | <b>`point`</b>                | Addon type specification<br>At all addon types and for this kind always <b>"kodi.audioencoder"</b>.
/// | <b>`library_@PLATFORM@`</b>   | Sets the used library name, which is automatically set by cmake at addon build.
/// | <b>`extension`</b>            | The file extensions / styles supported by this addon.
///
/// --------------------------------------------------------------------------
///
/// --------------------------------------------------------------------------
///
/// **Here is a code example how this addon is used:**
///
/// ~~~~~~~~~~~~~{.cpp}
/// #include <kodi/addon-instance/AudioEncoder.h>
///
/// class ATTRIBUTE_HIDDEN CMyAudioEncoder : public kodi::addon::CInstanceAudioEncoder
/// {
/// public:
///   CMyAudioEncoder(KODI_HANDLE instance, const std::string& kodiVersion)
///     : kodi::addon::CInstanceAudioEncoder(instance, kodiVersion)
///
///   bool Init(const std::string& filename, unsigned int filecache,
///             int& channels, int& samplerate,
///             int& bitspersample, int64_t& totaltime,
///             int& bitrate, AEDataFormat& format,
///             std::vector<AEChannel>& channellist) override;
///   int Encode(int numBytesRead, const uint8_t* pbtStream) override;
///   bool Finish() override; // Optional
/// };
///
/// CMyAudioEncoder::CMyAudioEncoder(KODI_HANDLE instance)
///   : kodi::addon::CInstanceAudioEncoder(instance)
/// {
///   ...
/// }
///
/// bool CMyAudioEncoder::Start(int inChannels,
///                             int inRate,
///                             int inBits,
///                             const std::string& title,
///                             const std::string& artist,
///                             const std::string& albumartist,
///                             const std::string& album,
///                             const std::string& year,
///                             const std::string& track,
///                             const std::string& genre,
///                             const std::string& comment,
///                             int trackLength)
/// {
///   ...
///   return true;
/// }
///
/// int CMyAudioEncoder::Encode(int numBytesRead, const uint8_t* pbtStream)
/// {
///   uint8_t* data = nullptr;
///   int length = 0;
///   ...
///   kodi::addon::CInstanceAudioEncoder::Write(data, length);
///
///   return 0;
/// }
///
///
/// bool CMyAudioEncoder::Finish()
/// {
///   ...
///   return true;
/// }
///
/// //----------------------------------------------------------------------
///
/// class CMyAddon : public kodi::addon::CAddonBase
/// {
/// public:
///   CMyAddon() = default;
///   ADDON_STATUS CreateInstance(int instanceType,
///                               const std::string& instanceID,
///                               KODI_HANDLE instance,
///                               const std::string& version,
///                               KODI_HANDLE& addonInstance) override;
/// };
///
/// // If you use only one instance in your add-on, can be instanceType and
/// // instanceID ignored
/// ADDON_STATUS CMyAddon::CreateInstance(int instanceType,
///                                       const std::string& instanceID,
///                                       KODI_HANDLE instance,
///                                       const std::string& version,
///                                       KODI_HANDLE& addonInstance)
/// {
///   if (instanceType == ADDON_INSTANCE_AUDIOENCODER)
///   {
///     kodi::Log(ADDON_LOG_INFO, "Creating my audio encoder instance");
///     addonInstance = new CMyAudioEncoder(instance, version);
///     return ADDON_STATUS_OK;
///   }
///   else if (...)
///   {
///     ...
///   }
///   return ADDON_STATUS_UNKNOWN;
/// }
///
/// ADDONCREATOR(CMyAddon)
/// ~~~~~~~~~~~~~
///
/// The destruction of the example class `CMyAudioEncoder` is called from
/// Kodi's header. Manually deleting the add-on instance is not required.
///
class ATTRIBUTE_HIDDEN CInstanceAudioEncoder : public IAddonInstance
{
public:
  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Audio encoder class constructor used to support multiple instances.
  ///
  /// @param[in] instance The instance value given to
  ///                     <b>`kodi::addon::CAddonBase::CreateInstance(...)`</b>.
  /// @param[in] kodiVersion [opt] Version used in Kodi for this instance, to
  ///                        allow compatibility to older Kodi versions.
  ///
  /// @note Recommended to set <b>`kodiVersion`</b>.
  ///
  ///
  /// --------------------------------------------------------------------------
  ///
  /// **Here's example about the use of this:**
  /// ~~~~~~~~~~~~~{.cpp}
  /// class CMyAudioEncoder : public kodi::addon::CInstanceAudioEncoder
  /// {
  /// public:
  ///   CMyAudioEncoder(KODI_HANDLE instance, const std::string& kodiVersion)
  ///     : kodi::addon::CInstanceAudioEncoder(instance, kodiVersion)
  ///   {
  ///      ...
  ///   }
  ///
  ///   ...
  /// };
  ///
  /// ADDON_STATUS CMyAddon::CreateInstance(int instanceType,
  ///                                       const std::string& instanceID,
  ///                                       KODI_HANDLE instance,
  ///                                       const std::string& version,
  ///                                       KODI_HANDLE& addonInstance)
  /// {
  ///   kodi::Log(ADDON_LOG_INFO, "Creating my audio encoder instance");
  ///   addonInstance = new CMyAudioEncoder(instance, version);
  ///   return ADDON_STATUS_OK;
  /// }
  /// ~~~~~~~~~~~~~
  ///
  explicit CInstanceAudioEncoder(KODI_HANDLE instance, const std::string& kodiVersion = "")
    : IAddonInstance(ADDON_INSTANCE_AUDIOENCODER,
                     !kodiVersion.empty() ? kodiVersion
                                          : GetKodiTypeVersion(ADDON_INSTANCE_AUDIOENCODER))
  {
    if (CAddonBase::m_interface->globalSingleInstance != nullptr)
      throw std::logic_error("kodi::addon::CInstanceAudioEncoder: Creation of multiple together "
                             "with single instance way is not allowed!");

    SetAddonStruct(instance);
  }
  //----------------------------------------------------------------------------

  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Start encoder (**required**)
  ///
  /// @param[in] inChannels Number of channels
  /// @param[in] inRate Sample rate of input data
  /// @param[in] inBits Bits per sample in input data
  /// @param[in] title The title of the song
  /// @param[in] artist The artist of the song
  /// @param[in] albumartist The albumartist of the song
  /// @param[in] year The year of the song
  /// @param[in] track The track number of the song
  /// @param[in] genre The genre of the song
  /// @param[in] comment A comment to attach to the song
  /// @param[in] trackLength Total track length in seconds
  /// @return True on success, false on failure.
  ///
  virtual bool Start(int inChannels,
                     int inRate,
                     int inBits,
                     const std::string& title,
                     const std::string& artist,
                     const std::string& albumartist,
                     const std::string& album,
                     const std::string& year,
                     const std::string& track,
                     const std::string& genre,
                     const std::string& comment,
                     int trackLength) = 0;
  //----------------------------------------------------------------------------

  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Encode a chunk of audio (**required**)
  ///
  /// @param[in] numBytesRead Number of bytes in input buffer
  /// @param[in] pbtStream The input buffer
  /// @return Number of bytes consumed
  ///
  virtual int Encode(int numBytesRead, const uint8_t* pbtStream) = 0;
  //----------------------------------------------------------------------------

  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Finalize encoding (**optional**)
  ///
  /// @return True on success, false on failure.
  ///
  virtual bool Finish() { return true; }
  //----------------------------------------------------------------------------

  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Write block of data
  ///
  /// @param[in] data Pointer to the array of elements to be written
  /// @param[in] length Size in bytes to be written.
  /// @return The total number of bytes successfully written is returned.
  ///
  /// @remarks Only called from addon itself.
  ///
  int Write(const uint8_t* data, int length)
  {
    return m_instanceData->toKodi->write(m_instanceData->toKodi->kodiInstance, data, length);
  }
  //----------------------------------------------------------------------------

  //============================================================================
  /// @ingroup cpp_kodi_addon_audioencoder
  /// @brief Set the file's current position.
  ///
  /// The whence argument is optional and defaults to SEEK_SET (0)
  ///
  /// @param[in] position The position that you want to seek to
  /// @param[in] whence [optional] offset relative to\n
  ///                              You can set the value of whence to one
  ///                              of three things:
  ///  |   Value  | int | Description                                        |
  ///  |:--------:|:---:|:---------------------------------------------------|
  ///  | 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.
  ///  | 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."
  ///  | 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.
  ///
  /// @return Returns the resulting offset location as measured in bytes from
  ///         the beginning of the file. On error, the value -1 is returned.
  ///
  /// @remarks Only called from addon itself.
  ///
  int64_t Seek(int64_t position, int whence = SEEK_SET)
  {
    return m_instanceData->toKodi->seek(m_instanceData->toKodi->kodiInstance, position, whence);
  }
  //----------------------------------------------------------------------------

private:
  void SetAddonStruct(KODI_HANDLE instance)
  {
    if (instance == nullptr)
      throw std::logic_error("kodi::addon::CInstanceAudioEncoder: Creation with empty addon "
                             "structure not allowed, table must be given from Kodi!");

    m_instanceData = static_cast<AddonInstance_AudioEncoder*>(instance);
    m_instanceData->toAddon->addonInstance = this;
    m_instanceData->toAddon->start = ADDON_Start;
    m_instanceData->toAddon->encode = ADDON_Encode;
    m_instanceData->toAddon->finish = ADDON_Finish;
  }

  inline static bool ADDON_Start(const AddonInstance_AudioEncoder* instance,
                                 int inChannels,
                                 int inRate,
                                 int inBits,
                                 const char* title,
                                 const char* artist,
                                 const char* albumartist,
                                 const char* album,
                                 const char* year,
                                 const char* track,
                                 const char* genre,
                                 const char* comment,
                                 int trackLength)
  {
    return static_cast<CInstanceAudioEncoder*>(instance->toAddon->addonInstance)
        ->Start(inChannels, inRate, inBits, title, artist, albumartist, album, year, track, genre,
                comment, trackLength);
  }

  inline static int ADDON_Encode(const AddonInstance_AudioEncoder* instance,
                                 int numBytesRead,
                                 const uint8_t* pbtStream)
  {
    return static_cast<CInstanceAudioEncoder*>(instance->toAddon->addonInstance)
        ->Encode(numBytesRead, pbtStream);
  }

  inline static bool ADDON_Finish(const AddonInstance_AudioEncoder* instance)
  {
    return static_cast<CInstanceAudioEncoder*>(instance->toAddon->addonInstance)->Finish();
  }

  AddonInstance_AudioEncoder* m_instanceData;
};

} /* namespace addon */
} /* namespace kodi */

#endif /* __cplusplus */