#pragma once /* * Copyright (C) 2005-2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kodi; see the file COPYING. If not, see * . * */ #include "../AddonBase.h" #ifdef BUILD_KODI_ADDON #include "../AEChannelData.h" #else #include "cores/AudioEngine/Utils/AEChannelData.h" #endif #include namespace kodi { namespace addon { class CInstanceAudioDecoder; }} extern "C" { typedef struct AddonProps_AudioDecoder { int dummy; } AddonProps_AudioDecoder; typedef struct AddonToKodiFuncTable_AudioDecoder { void* kodiInstance; } AddonToKodiFuncTable_AudioDecoder; struct AddonInstance_AudioDecoder; typedef struct KodiToAddonFuncTable_AudioDecoder { kodi::addon::CInstanceAudioDecoder* addonInstance; bool (__cdecl* init) (const AddonInstance_AudioDecoder* instance, const char* file, unsigned int filecache, int* channels, int* samplerate, int* bitspersample, int64_t* totaltime, int* bitrate, AEDataFormat* format, const AEChannel** info); int (__cdecl* read_pcm) (const AddonInstance_AudioDecoder* instance, uint8_t* buffer, int size, int* actualsize); int64_t (__cdecl* seek) (const AddonInstance_AudioDecoder* instance, int64_t time); bool (__cdecl* read_tag) (const AddonInstance_AudioDecoder* instance, const char* file, char* title, char* artist, int* length); int (__cdecl* track_count) (const AddonInstance_AudioDecoder* instance, const char* file); } KodiToAddonFuncTable_AudioDecoder; typedef struct AddonInstance_AudioDecoder { AddonProps_AudioDecoder props; AddonToKodiFuncTable_AudioDecoder toKodi; KodiToAddonFuncTable_AudioDecoder toAddon; } AddonInstance_AudioDecoder; } /* extern "C" */ namespace kodi { namespace addon { class CInstanceAudioDecoder : public IAddonInstance { public: //========================================================================== /// @brief Class constructor /// /// @param[in] instance The from Kodi given instance given be /// add-on CreateInstance call with instance /// id ADDON_INSTANCE_AUDIODECODER. explicit CInstanceAudioDecoder(KODI_HANDLE instance) : IAddonInstance(ADDON_INSTANCE_AUDIODECODER) { if (CAddonBase::m_interface->globalSingleInstance != nullptr) throw std::logic_error("kodi::addon::CInstanceAudioDecoder: Creation of multiple together with single instance way is not allowed!"); SetAddonStruct(instance); } //-------------------------------------------------------------------------- //========================================================================== /// @ingroup cpp_kodi_addon_audiodecoder /// @brief Initialize a decoder /// /// @param[in] filename The file to read /// @param[in] filecache The file cache size /// @param[out] channels Number of channels in output stream /// @param[out] samplerate Samplerate of output stream /// @param[out] bitspersample Bits per sample in output stream /// @param[out] totaltime Total time for stream /// @param[out] bitrate Average bitrate of input stream /// @param[out] format Data format for output stream /// @param[out] channellist Channel mapping for output stream /// @return true if successfully done, otherwise /// false /// virtual bool Init(const std::string& filename, unsigned int filecache, int& channels, int& samplerate, int& bitspersample, int64_t& totaltime, int& bitrate, AEDataFormat& format, std::vector& channellist) = 0; //-------------------------------------------------------------------------- //========================================================================== /// @ingroup cpp_kodi_addon_audiodecoder /// @brief Produce some noise /// /// @param[in] buffer Output buffer /// @param[in] size Size of output buffer /// @param[out] actualsize Actual number of bytes written to output buffer /// @return Return with following possible values: /// | Value | Description | /// |:-----:|:-----------------------------| /// | 0 | on success /// | -1 | on end of stream /// | 1 | on failure /// virtual int ReadPCM(uint8_t* buffer, int size, int& actualsize) = 0; //-------------------------------------------------------------------------- //========================================================================== /// @ingroup cpp_kodi_addon_audiodecoder /// @brief Seek in output stream /// /// @param[in] time Time position to seek to in milliseconds /// @return Time position seek ended up on /// virtual int64_t Seek(int64_t time) { return time; } //-------------------------------------------------------------------------- //========================================================================== /// @ingroup cpp_kodi_addon_audiodecoder /// @brief Read tag of a file /// /// @param[in] file File to read tag for /// @param[out] title Title of file /// @param[out] artist Artist of file /// @param[out] length Length of file /// @return True on success, false on failure /// virtual bool ReadTag(const std::string& file, std::string& title, std::string& artist, int& length) { return false; } //-------------------------------------------------------------------------- //========================================================================== /// @ingroup cpp_kodi_addon_audiodecoder /// @brief Get number of tracks in a file /// /// @param[in] file File to read tag for /// @return Number of tracks in file /// virtual int TrackCount(const std::string& file) { return 1; } //-------------------------------------------------------------------------- private: void SetAddonStruct(KODI_HANDLE instance) { if (instance == nullptr) throw std::logic_error("kodi::addon::CInstanceAudioDecoder: Creation with empty addon structure not allowed, table must be given from Kodi!"); m_instanceData = static_cast(instance); m_instanceData->toAddon.addonInstance = this; m_instanceData->toAddon.init = ADDON_Init; m_instanceData->toAddon.read_pcm = ADDON_ReadPCM; m_instanceData->toAddon.seek = ADDON_Seek; m_instanceData->toAddon.read_tag = ADDON_ReadTag; m_instanceData->toAddon.track_count = ADDON_TrackCount; } inline static bool ADDON_Init(const AddonInstance_AudioDecoder* instance, const char* file, unsigned int filecache, int* channels, int* samplerate, int* bitspersample, int64_t* totaltime, int* bitrate, AEDataFormat* format, const AEChannel** info) { instance->toAddon.addonInstance->m_channelList.clear(); bool ret = instance->toAddon.addonInstance->Init(file, filecache, *channels, *samplerate, *bitspersample, *totaltime, *bitrate, *format, instance->toAddon.addonInstance->m_channelList); if (!instance->toAddon.addonInstance->m_channelList.empty()) { if (instance->toAddon.addonInstance->m_channelList.back() != AE_CH_NULL) instance->toAddon.addonInstance->m_channelList.push_back(AE_CH_NULL); *info = instance->toAddon.addonInstance->m_channelList.data(); } else *info = nullptr; return ret; } inline static int ADDON_ReadPCM(const AddonInstance_AudioDecoder* instance, uint8_t* buffer, int size, int* actualsize) { return instance->toAddon.addonInstance->ReadPCM(buffer, size, *actualsize); } inline static int64_t ADDON_Seek(const AddonInstance_AudioDecoder* instance, int64_t time) { return instance->toAddon.addonInstance->Seek(time); } inline static bool ADDON_ReadTag(const AddonInstance_AudioDecoder* instance, const char* file, char* title, char* artist, int* length) { std::string intTitle; std::string intArtist; bool ret = instance->toAddon.addonInstance->ReadTag(file, intTitle, intArtist, *length); if (ret) { strncpy(title, intTitle.c_str(), ADDON_STANDARD_STRING_LENGTH_SMALL-1); strncpy(artist, intArtist.c_str(), ADDON_STANDARD_STRING_LENGTH_SMALL-1); } return ret; } inline static int ADDON_TrackCount(const AddonInstance_AudioDecoder* instance, const char* file) { return instance->toAddon.addonInstance->TrackCount(file); } std::vector m_channelList; AddonInstance_AudioDecoder* m_instanceData; }; } /* namespace addon */ } /* namespace kodi */