#pragma once /* * Copyright (C) 2005-2014 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 #include #include #include #include #include "kodi_audioengine_types.h" #ifdef BUILD_KODI_ADDON #include "kodi/AudioEngine/AEChannelData.h" #include "kodi/AudioEngine/AEChannelInfo.h" #include "kodi/AudioEngine/AEStreamData.h" #else #include "cores/AudioEngine/Utils/AEChannelData.h" #include "cores/AudioEngine/Utils/AEChannelInfo.h" #include "cores/AudioEngine/Utils/AEStreamData.h" #endif #include "libXBMC_addon.h" #ifdef _WIN32 #define AUDIOENGINE_HELPER_DLL "\\library.kodi.audioengine\\libKODI_audioengine" ADDON_HELPER_EXT #else #define AUDIOENGINE_HELPER_DLL_NAME "libKODI_audioengine-" ADDON_HELPER_ARCH ADDON_HELPER_EXT #define AUDIOENGINE_HELPER_DLL "/library.kodi.audioengine/" AUDIOENGINE_HELPER_DLL_NAME #endif class CAddonAEStream; class CHelper_libKODI_audioengine { public: CHelper_libKODI_audioengine(void) { m_libKODI_audioengine = NULL; m_Handle = NULL; } ~CHelper_libKODI_audioengine(void) { if (m_libKODI_audioengine) { AudioEngine_unregister_me(m_Handle, m_Callbacks); dlclose(m_libKODI_audioengine); } } /*! * @brief Resolve all callback methods * @param handle Pointer to the add-on * @return True when all methods were resolved, false otherwise. */ bool RegisterMe(void* handle) { m_Handle = handle; std::string libBasePath; libBasePath = ((cb_array*)m_Handle)->libPath; libBasePath += AUDIOENGINE_HELPER_DLL; #if defined(ANDROID) struct stat st; if(stat(libBasePath.c_str(),&st) != 0) { std::string tempbin = getenv("XBMC_ANDROID_LIBS"); libBasePath = tempbin + "/" + AUDIOENGINE_HELPER_DLL; } #endif m_libKODI_audioengine = dlopen(libBasePath.c_str(), RTLD_LAZY); if (m_libKODI_audioengine == NULL) { fprintf(stderr, "Unable to load %s\n", dlerror()); return false; } AudioEngine_register_me = (void* (*)(void *HANDLE)) dlsym(m_libKODI_audioengine, "AudioEngine_register_me"); if (AudioEngine_register_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } AudioEngine_unregister_me = (void(*)(void* HANDLE, void* CB)) dlsym(m_libKODI_audioengine, "AudioEngine_unregister_me"); if (AudioEngine_unregister_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } AudioEngine_MakeStream = (CAddonAEStream* (*)(void*, void*, AudioEngineFormat, unsigned int)) dlsym(m_libKODI_audioengine, "AudioEngine_make_stream"); if (AudioEngine_MakeStream == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } AudioEngine_FreeStream = (void(*)(CAddonAEStream*)) dlsym(m_libKODI_audioengine, "AudioEngine_free_stream"); if (AudioEngine_FreeStream == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } AudioEngine_GetCurrentSinkFormat = (bool(*)(void*, void*, AudioEngineFormat*)) dlsym(m_libKODI_audioengine, "AudioEngine_get_current_sink_Format"); if (AudioEngine_GetCurrentSinkFormat == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } m_Callbacks = AudioEngine_register_me(m_Handle); return m_Callbacks != NULL; } /** * Creates and returns a new handle to an IAEStream in the format specified, this function should never fail * @param DataFormat The data format the incoming audio will be in (eg, AE_FMT_S16LE) * @param SampleRate The sample rate of the audio data (eg, 48000) * @param ChannelLayout The order of the channels in the audio data * @param Options A bit field of stream options (see: enum AEStreamOptions) * @return a new Handle to an IAEStream that will accept data in the requested format */ CAddonAEStream* MakeStream(AudioEngineFormat Format, unsigned int Options = 0) { return AudioEngine_MakeStream(m_Handle, m_Callbacks, Format, Options); } /** * This method will remove the specifyed stream from the engine. * For OSX/IOS this is essential to reconfigure the audio output. * @param stream The stream to be altered * @return NULL */ void FreeStream(CAddonAEStream **Stream) { AudioEngine_FreeStream(*Stream); *Stream = NULL; } /** * Get the current sink data format * * @param Current sink data format. For more details see AudioEngineFormat. * @return Returns true on success, else false. */ bool GetCurrentSinkFormat(AudioEngineFormat &SinkFormat) { return AudioEngine_GetCurrentSinkFormat(m_Handle, m_Callbacks, &SinkFormat); } protected: void* (*AudioEngine_register_me)(void*); void (*AudioEngine_unregister_me)(void*, void*); CAddonAEStream* (*AudioEngine_MakeStream)(void*, void*, AudioEngineFormat, unsigned int); bool (*AudioEngine_GetCurrentSinkFormat)(void*, void*, AudioEngineFormat *SinkFormat); void (*AudioEngine_FreeStream)(CAddonAEStream*); private: void* m_libKODI_audioengine; void* m_Handle; void* m_Callbacks; struct cb_array { const char* libPath; }; }; // Audio Engine Stream Class class CAddonAEStream { public: CAddonAEStream(void *Addon, void *Callbacks, AEStreamHandle *StreamHandle); virtual ~CAddonAEStream(); /** * Returns the amount of space available in the stream * @return The number of bytes AddData will consume */ virtual unsigned int GetSpace(); /** * Add planar or interleaved PCM data to the stream * @param Data array of pointers to the planes * @param Offset to frame in frames * @param Frames number of frames * @return The number of frames consumed */ virtual unsigned int AddData(uint8_t* const *Data, unsigned int Offset, unsigned int Frames); /** * Returns the time in seconds that it will take * for the next added packet to be heard from the speakers. * @return seconds */ virtual double GetDelay(); /** * Returns if the stream is buffering * @return True if the stream is buffering */ virtual bool IsBuffering(); /** * Returns the time in seconds that it will take * to underrun the cache if no sample is added. * @return seconds */ virtual double GetCacheTime(); /** * Returns the total time in seconds of the cache * @return seconds */ virtual double GetCacheTotal(); /** * Pauses the stream playback */ virtual void Pause(); /** * Resumes the stream after pausing */ virtual void Resume(); /** * Start draining the stream * @note Once called AddData will not consume more data. */ virtual void Drain(bool Wait); /** * Returns true if the is stream draining */ virtual bool IsDraining(); /** * Returns true if the is stream has finished draining */ virtual bool IsDrained(); /** * Flush all buffers dropping the audio data */ virtual void Flush(); /** * Return the stream's current volume level * @return The volume level between 0.0 and 1.0 */ virtual float GetVolume(); /** * Set the stream's volume level * @param volume The new volume level between 0.0 and 1.0 */ virtual void SetVolume(float Volume); /** * Gets the stream's volume amplification in linear units. * @return The volume amplification factor between 1.0 and 1000.0 */ virtual float GetAmplification(); /** * Sets the stream's volume amplification in linear units. * @param The volume amplification factor between 1.0 and 1000.0 */ virtual void SetAmplification(float Amplify); /** * Returns the size of one audio frame in bytes (channelCount * resolution) * @return The size in bytes of one frame */ virtual const unsigned int GetFrameSize() const; /** * Returns the number of channels the stream is configured to accept * @return The channel count */ virtual const unsigned int GetChannelCount() const; /** * Returns the stream's sample rate, if the stream is using a dynamic sample rate, this value will NOT reflect any changes made by calls to SetResampleRatio() * @return The stream's sample rate (eg, 48000) */ virtual const unsigned int GetSampleRate() const; /** * Return the data format the stream has been configured with * @return The stream's data format (eg, AE_FMT_S16LE) */ virtual const AEDataFormat GetDataFormat() const; /** * Return the resample ratio * @note This will return an undefined value if the stream is not resampling * @return the current resample ratio or undefined if the stream is not resampling */ virtual double GetResampleRatio(); /** * Sets the resample ratio * @note This function may return false if the stream is not resampling, if you wish to use this be sure to set the AESTREAM_FORCE_RESAMPLE option * @param ratio the new sample rate ratio, calculated by ((double)desiredRate / (double)GetSampleRate()) */ virtual void SetResampleRatio(double Ratio); private: AEStreamHandle *m_StreamHandle; void *m_Callbacks; void *m_AddonHandle; };