diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6611cd8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,43 @@ +language: cpp + +# +# Define the build matrix +# +# Travis defaults to building on Ubuntu Precise when building on +# Linux. We need Trusty in order to get up to date versions of +# cmake and g++. +# +matrix: + include: + - os: linux + dist: trusty + sudo: required + compiler: gcc + - os: linux + dist: trusty + sudo: required + compiler: clang + - os: osx + osx_image: xcode7.3 + - os: osx + osx_image: xcode6.1 + +# +# Some of the OS X images don't have cmake, contrary to what people +# on the Internet say +# +before_install: + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew update ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew install cmake ; fi + +# +# The addon source is automatically checked out in $TRAVIS_BUILD_DIR, +# we'll put the Kodi source on the same level +# +before_script: + - cd $TRAVIS_BUILD_DIR/.. + - git clone --depth=1 https://github.com/xbmc/xbmc.git + - cd adsp.template && mkdir build && cd build + - cmake -DADDONS_TO_BUILD=adsp.template -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/project/cmake/addons + +script: make diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..45d8b55 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,79 @@ +project(adsp_base) + +#find_package(p8-platform REQUIRED) + +set(SOURCES adsp.template/ADSPHelpers.cpp + adsp.template/client.cpp + adsp.template/GUIDialogBase.cpp + adsp.template/Addon/MVC/Interfaces/Controller/IController.hpp + adsp.template/Addon/MVC/Interfaces/Model/IModel.hpp + adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp + adsp.template/Addon/MVC/Model/TParameter.hpp + adsp.template/Addon/MessageSystem/Communication/Message.cpp + adsp.template/Addon/MessageSystem/Communication/ActorProtocol.cpp + adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.hpp + adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.cpp + adsp.template/Addon/MessageSystem/Sockets/TSocketMemcpy.hpp + adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp + adsp.template/Addon/Utils/EnumIDsToString.hpp + adsp.template/Addon/Process/AddonProcessManager.cpp + adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.cpp + adsp.template/AudioDSP/Streams/ADSPStreamManager.cpp + adsp.template/AudioDSP/Streams/ADSPStream.cpp + adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.cpp + adsp.template/Settings/SettingsHelpers.cpp + adsp.template/Settings/SettingsManager.cpp) + +set(HEADERS adsp.template/ADSPHelpers.h + adsp.template/doxygenDocu.h + adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp + adsp.template/Addon/MessageSystem/Communication/ActorProtocol.h + adsp.template/Addon/MessageSystem/Communication/Message.hpp + adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp + adsp.template/Addon/Process/AddonProcessManager.hpp + adsp.template/Addon/Process/IAddonProcess.hpp + adsp.template/AddonExceptions/IAddonException.h + adsp.template/AddonExceptions/TAddonException.h + adsp.template/configuration/templateConfiguration.h + adsp.template/include/checkTemplateConfig.h + adsp.template/include/client.h + adsp.template/include/GUIDialogBase.h + adsp.template/include/MACROHelper.h + adsp.template/include/typedefs.h + adsp.template/Settings/ISettingsElement.h + adsp.template/Settings/SettingsHelpers.h + adsp.template/Settings/SettingsManager.h + adsp.template/Settings/TSettingsElement.h + + adsp.template/Addon/MVC/Interfaces/View/IView.hpp + adsp.template/Addon/MVC/Interfaces/View/ActionIDs.hpp + adsp.template/Addon/Utils/TCreationStatistics.hpp + adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp + adsp.template/AudioDSP/FactoryADSPModes/IADSPMode.hpp + adsp.template/AudioDSP/Streams/ADSPStreamManager.hpp + adsp.template/AudioDSP/Streams/ADSPStream.hpp + adsp.template/AudioDSP/Streams/IADSPStreamBuilder.hpp + adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.hpp + + adsp.template/utils/stdStringUtils.h) + +addon_source_group("${SOURCES}") +addon_source_group("${HEADERS}") + +include_directories(${kodiplatform_INCLUDE_DIRS} + ${p8-platform_INCLUDE_DIRS} + ${KODI_INCLUDE_DIR}) + +add_library(${PROJECT_NAME} STATIC ${SOURCES} ${HEADERS}) +add_library(adsp::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +target_include_directories(${PROJECT_NAME} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/adsp.template + INTERFACE $ + $) + +target_link_libraries(${PROJECT_NAME} kodi::KodiThreads) + +# install all specific module files +#asplib_install_module(${PROJECT_NAME} "${HEADERS}" ${CMAKE_INSTALL_PREFIX}/include) +install(TARGETS ${PROJECT_NAME} EXPORT adsp DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) diff --git a/FindTinyXML.cmake b/FindTinyXML.cmake new file mode 100644 index 0000000..1e8258c --- /dev/null +++ b/FindTinyXML.cmake @@ -0,0 +1,28 @@ +# - Find TinyXML +# Find the native TinyXML includes and library +# +# TINYXML_FOUND - True if TinyXML found. +# TINYXML_INCLUDE_DIRS - where to find tinyxml.h, etc. +# TINYXML_LIBRARIES - List of libraries when using TinyXML. +# + +if(PKG_CONFIG_FOUND) + pkg_check_modules (TINYXML tinyxml) + list(APPEND TINYXML_INCLUDE_DIRS ${TINYXML_INCLUDEDIR}) +endif() + +if(NOT TINYXML_FOUND) + find_path(TINYXML_INCLUDE_DIRS "tinyxml.h" + PATH_SUFFIXES "tinyxml" ) + + find_library( TINYXML_LIBRARIES + NAMES "tinyxml" + PATH_SUFFIXES "tinyxml" ) +endif() + +# handle the QUIETLY and REQUIRED arguments and set TINYXML_FOUND to TRUE if +# all listed variables are TRUE +include( "FindPackageHandleStandardArgs" ) +find_package_handle_standard_args(TinyXML DEFAULT_MSG TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES ) + +mark_as_advanced(TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES) diff --git a/README.md b/README.md new file mode 100644 index 0000000..5eb94fd --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +#### CI Testing +* Tarvis-CI for OS X, iOS, Linux [![Build Status](https://travis-ci.org/kodi-adsp/adsp.template.svg?branch=master)](https://travis-ci.org/kodi-adsp/adsp.template) +* AppVeyor for Windows [![Build status](https://ci.appveyor.com/api/projects/status/p3pd175e1leas49a/branch/master?svg=true)](https://ci.appveyor.com/project/AchimTuran/adsp-template/branch/master) +* Code analyses for Linux [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) + + +ADSP Template Addon +============== +You can use this template to see how the ADSP Addon API works or to start a new ADSP Addon. +Preprocessing only copies input to output. +Master process implements a simple channel upmixer (e.g. stereo to 5.1) by copying the input channel to output channels. +Postprocessing copies input samples to output. + + +ADSP Addon API Documentation +============== +For more details see: http://wisler.bplaced.de/xbmc-adsp-addons/ + +## Build instructions for Kodi's binary add-ons + +When building the addon you have to use the correct branch depending on which version of Kodi you're building against. +For example, if you're building the `Jarvis` branch of Kodi you should checkout the `Jarvis` branch of this repository. +Addon releases are also tagged regularly. + +For further instructions replace `{addon-id}` and `{org}` with the repository- and the Github organisation-name. +E.g. `https://github.com/kodi-adsp/adsp.basic.git` results in `{addon-id}=adsp.basic` and `{org}=kodi-adsp` + +With the following instructions the add-on files will be placed in `../../xbmc/addons`. Consequently this adds a system add-on, which can be used direclty if you build Kodi from source. + +### Linux + +1. `git clone https://github.com/xbmc/xbmc.git` +2. `git clone https://github.com/{org}/{addon-id}.git` +3. `cd {addon-id} && mkdir build && cd build` +4. `cmake -DADDONS_TO_BUILD={addon-id} -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/project/cmake/addons` +5. `make` + +### Windows + +Use the visual studio command line or run `call "%VS120COMNTOOLS%..\..\VC\bin\vcvars32.bat"` + +1. `git clone https://github.com/xbmc/xbmc.git` +2. `git clone https://github.com/{org}/{addon-id}.git` +3. `cd {addon-id} && mkdir build && cd build` +4. `cmake -G "NMake Makefiles" -DADDONS_TO_BUILD={addon-id} -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/project/cmake/addons` +5. `cmake --build "%cd%" --target "{addon-id}"` + + +## Useful links + +* [Kodi's PVR user support] (http://forum.kodi.tv/forumdisplay.php?fid=167) +* [General binary add-on development] (http://forum.kodi.tv/forumdisplay.php?fid=26) +* [Kodi Core development support] (http://forum.kodi.tv/forumdisplay.php?fid=93) +* [Kodi AudioDSP development support] (http://forum.kodi.tv/forumdisplay.php?fid=235) +* [Kodi Screensavers and Visualisations development support] (http://forum.kodi.tv/forumdisplay.php?fid=38) +* [Kodi PVR development support] (http://forum.kodi.tv/forumdisplay.php?fid=136) + +------------- +#### License +[GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007](https://github.com/kodi-adsp/adsp.template/blob/master/LICENSE.md) + diff --git a/adsp.template/ADSPHelpers.cpp b/adsp.template/ADSPHelpers.cpp new file mode 100644 index 0000000..aa775d4 --- /dev/null +++ b/adsp.template/ADSPHelpers.cpp @@ -0,0 +1,504 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +#include "ADSPHelpers.h" +#include +using namespace std; + +#if !defined(TARGET_WINDOWS) + inline float abs(float Val) + { + if(Val >= 0.0f) + { + return Val; + } + else + { + return -1.0f*Val; + } + } +#endif + +AE_DSP_MENUHOOK_CAT CADSPHelpers::Translate_ADSPModeType_TO_MenuHook(AE_DSP_MODE_TYPE ModeType) +{ + AE_DSP_MENUHOOK_CAT menuHookCat = AE_DSP_MENUHOOK_UNKNOWN; + switch (ModeType) + { + case AE_DSP_MODE_TYPE_INPUT_RESAMPLE: + menuHookCat = AE_DSP_MENUHOOK_RESAMPLE; + break; + + case AE_DSP_MODE_TYPE_PRE_PROCESS: + menuHookCat = AE_DSP_MENUHOOK_PRE_PROCESS; + break; + + case AE_DSP_MODE_TYPE_MASTER_PROCESS: + menuHookCat = AE_DSP_MENUHOOK_MASTER_PROCESS; + break; + + case AE_DSP_MODE_TYPE_POST_PROCESS: + menuHookCat = AE_DSP_MENUHOOK_POST_PROCESS; + break; + + case AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE: + menuHookCat = AE_DSP_MENUHOOK_RESAMPLE; + break; + } + + return menuHookCat; +} + +// Channel Layouts and channel names are from: https://trac.ffmpeg.org/wiki/AudioChannelManipulation +AE_DSP_CHANNEL CADSPHelpers::Translate_ChFlag_TO_ChID(AE_DSP_CHANNEL_PRESENT ChFlag) +{ + switch(ChFlag) + { + case AE_DSP_PRSNT_CH_FL: + return AE_DSP_CH_FL; + break; + + case AE_DSP_PRSNT_CH_FR: + return AE_DSP_CH_FR; + break; + + case AE_DSP_PRSNT_CH_FC: + return AE_DSP_CH_FC; + break; + + case AE_DSP_PRSNT_CH_LFE: + return AE_DSP_CH_LFE; + break; + + case AE_DSP_PRSNT_CH_BL: + return AE_DSP_CH_BL; + break; + + case AE_DSP_PRSNT_CH_BR: + return AE_DSP_CH_BR; + break; + + case AE_DSP_PRSNT_CH_FLOC: + return AE_DSP_CH_FLOC; + break; + + case AE_DSP_PRSNT_CH_FROC: + return AE_DSP_CH_FROC; + break; + + case AE_DSP_PRSNT_CH_BC: + return AE_DSP_CH_BC; + break; + + case AE_DSP_PRSNT_CH_SL: + return AE_DSP_CH_SL; + break; + + case AE_DSP_PRSNT_CH_SR: + return AE_DSP_CH_SR; + break; + + case AE_DSP_PRSNT_CH_TFL: + return AE_DSP_CH_TFL; + break; + + case AE_DSP_PRSNT_CH_TFR: + return AE_DSP_CH_TFR; + break; + + case AE_DSP_PRSNT_CH_TFC: + return AE_DSP_CH_TFC; + break; + + case AE_DSP_PRSNT_CH_TC: + return AE_DSP_CH_TC; + break; + + case AE_DSP_PRSNT_CH_TBL: + return AE_DSP_CH_TBL; + break; + + case AE_DSP_PRSNT_CH_TBR: + return AE_DSP_CH_TBR; + break; + + case AE_DSP_PRSNT_CH_TBC: + return AE_DSP_CH_TBC; + break; + + case AE_DSP_PRSNT_CH_BLOC: + return AE_DSP_CH_BLOC; + break; + + case AE_DSP_PRSNT_CH_BROC: + return AE_DSP_CH_BROC; + break; + + default: + return AE_DSP_CH_INVALID; + break; + } +} + +AE_DSP_CHANNEL_PRESENT CADSPHelpers::Translate_ChID_TO_ChFlag(AE_DSP_CHANNEL ChID) +{ + switch(ChID) + { + case AE_DSP_CH_FL: + return AE_DSP_PRSNT_CH_FL; + break; + + case AE_DSP_CH_FR: + return AE_DSP_PRSNT_CH_FR; + break; + + case AE_DSP_CH_FC: + return AE_DSP_PRSNT_CH_FC; + break; + + case AE_DSP_CH_LFE: + return AE_DSP_PRSNT_CH_LFE; + break; + + case AE_DSP_CH_BL: + return AE_DSP_PRSNT_CH_BL; + break; + + case AE_DSP_CH_BR: + return AE_DSP_PRSNT_CH_BR; + break; + + case AE_DSP_CH_FLOC: + return AE_DSP_PRSNT_CH_FLOC; + break; + + case AE_DSP_CH_FROC: + return AE_DSP_PRSNT_CH_FROC; + break; + + case AE_DSP_CH_BC: + return AE_DSP_PRSNT_CH_BC; + break; + + case AE_DSP_CH_SL: + return AE_DSP_PRSNT_CH_SL; + break; + + case AE_DSP_CH_SR: + return AE_DSP_PRSNT_CH_SR; + break; + + case AE_DSP_CH_TFL: + return AE_DSP_PRSNT_CH_TFL; + break; + + case AE_DSP_CH_TFR: + return AE_DSP_PRSNT_CH_TFR; + break; + + case AE_DSP_CH_TFC: + return AE_DSP_PRSNT_CH_TFC; + break; + + case AE_DSP_CH_TC: + return AE_DSP_PRSNT_CH_TC; + break; + + case AE_DSP_CH_TBL: + return AE_DSP_PRSNT_CH_TBL; + break; + + case AE_DSP_CH_TBR: + return AE_DSP_PRSNT_CH_TBR; + break; + + case AE_DSP_CH_TBC: + return AE_DSP_PRSNT_CH_TBC; + break; + + case AE_DSP_CH_BLOC: + return AE_DSP_PRSNT_CH_BLOC; + break; + + case AE_DSP_CH_BROC: + return AE_DSP_PRSNT_CH_BROC; + break; + + default: + return AE_DSP_PRSNT_CH_UNDEFINED; + break; + } +} + +string CADSPHelpers::Translate_ChFlag_TO_String(AE_DSP_CHANNEL_PRESENT ChFlag) +{ + string chStr = ""; + switch(ChFlag) + { + case AE_DSP_PRSNT_CH_FL: + chStr = "front left"; + break; + + case AE_DSP_PRSNT_CH_FR: + chStr = "front right"; + break; + + case AE_DSP_PRSNT_CH_FC: + chStr = "front center"; + break; + + case AE_DSP_PRSNT_CH_LFE: + chStr = "low frequency"; + break; + + case AE_DSP_PRSNT_CH_BL: + chStr = "back left"; + break; + + case AE_DSP_PRSNT_CH_BR: + chStr = "back right"; + break; + + case AE_DSP_PRSNT_CH_FLOC: + chStr = "front left-of-center"; + break; + + case AE_DSP_PRSNT_CH_FROC: + chStr = "front right-of-center"; + break; + + case AE_DSP_PRSNT_CH_BC: + chStr = "back center"; + break; + + case AE_DSP_PRSNT_CH_SL: + chStr = "side left"; + break; + + case AE_DSP_PRSNT_CH_SR: + chStr = "side right"; + break; + + case AE_DSP_PRSNT_CH_TFL: + chStr = "top front left"; + break; + + case AE_DSP_PRSNT_CH_TFR: + chStr = "top front right"; + break; + + case AE_DSP_PRSNT_CH_TFC: + chStr = "top front center"; + break; + + case AE_DSP_PRSNT_CH_TC: + chStr = "top center"; + break; + + case AE_DSP_PRSNT_CH_TBL: + chStr = "top back left"; + break; + + case AE_DSP_PRSNT_CH_TBR: + chStr = "top back right"; + break; + + case AE_DSP_PRSNT_CH_TBC: + chStr = "top back center"; + break; + + case AE_DSP_PRSNT_CH_BLOC: + chStr = "back left of center"; + break; + + case AE_DSP_PRSNT_CH_BROC: + chStr = "back right of center"; + break; + + default: + chStr = "undefined"; + break; + } + + return chStr; +} + +string CADSPHelpers::Translate_ChID_TO_String(AE_DSP_CHANNEL ChID) +{ + string chStr = ""; + switch(ChID) + { + case AE_DSP_CH_FL: + chStr = "front left"; + break; + + case AE_DSP_CH_FR: + chStr = "front right"; + break; + + case AE_DSP_CH_FC: + chStr = "front center"; + break; + + case AE_DSP_CH_LFE: + chStr = "low frequency"; + break; + + case AE_DSP_CH_BL: + chStr = "back left"; + break; + + case AE_DSP_CH_BR: + chStr = "back right"; + break; + + case AE_DSP_CH_FLOC: + chStr = "front left-of-center"; + break; + + case AE_DSP_CH_FROC: + chStr = "front right-of-center"; + break; + + case AE_DSP_CH_BC: + chStr = "back center"; + break; + + case AE_DSP_CH_SL: + chStr = "side left"; + break; + + case AE_DSP_CH_SR: + chStr = "side right"; + break; + + case AE_DSP_CH_TFL: + chStr = "top front left"; + break; + + case AE_DSP_CH_TFR: + chStr = "top front right"; + break; + + case AE_DSP_CH_TFC: + chStr = "top front center"; + break; + + case AE_DSP_CH_TC: + chStr = "top center"; + break; + + case AE_DSP_CH_TBL: + chStr = "top back left"; + break; + + case AE_DSP_CH_TBR: + chStr = "top back right"; + break; + + case AE_DSP_CH_TBC: + chStr = "top back center"; + break; + + case AE_DSP_CH_BLOC: + chStr = "back left of center"; + break; + + case AE_DSP_CH_BROC: + chStr = "back right of center"; + break; + + default: + chStr = "undefined"; + break; + } + + return chStr; +} + +bool CADSPHelpers::IsChannelFlag_Present(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL_PRESENT ChFlag) +{ + return (AvailableFlags & (ChFlag)) > 0; +} + +bool CADSPHelpers::IsChannelID_Present(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL ChID) +{ + return (AvailableFlags & (1< 0; +} + +AE_DSP_CHANNEL CADSPHelpers::GetNextChID(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL ChID) +{ + int retCh = AE_DSP_CH_INVALID; + for(int ii = ChID; ii < AE_DSP_CH_MAX; ii++) + { + if(AvailableFlags & 1<. + * + */ + + + +#include +// reserved for future implementation +//#include +#include +#include "ADSPHelpers.h" + +typedef unsigned long AE_DSP_CHANNEL_FLAGS; + +class CADSPHelpers +{ +public: + static AE_DSP_MENUHOOK_CAT Translate_ADSPModeType_TO_MenuHook(AE_DSP_MODE_TYPE ModeType); + static AE_DSP_CHANNEL Translate_ChFlag_TO_ChID(AE_DSP_CHANNEL_PRESENT ChFlag); + static AE_DSP_CHANNEL_PRESENT Translate_ChID_TO_ChFlag(AE_DSP_CHANNEL ChID); + static std::string Translate_ChFlag_TO_String(AE_DSP_CHANNEL_PRESENT ChFlag); + static std::string Translate_ChID_TO_String(AE_DSP_CHANNEL ChID); + static bool IsChannelFlag_Present(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL_PRESENT ChFlag); + static bool IsChannelID_Present(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL ChID); + static AE_DSP_CHANNEL_PRESENT GetNextChFlag(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL_PRESENT ChFlag); + static AE_DSP_CHANNEL GetNextChID(AE_DSP_CHANNEL_FLAGS AvailableFlags, AE_DSP_CHANNEL ChID); + static float Convert_dB_TO_Value(float dB); + static float Convert_Value_TO_dB(float Scale); + + /** @name Compare AudioDSP stream settings + */ + /*! + * @brief You can use this function to compare two stream settings. + * @param Settings1 First stream settings. + * @param Settings2 Second stream settings. + * @return True if they're equal otherwise false. + */ + static bool CmpStreamSettings(const AE_DSP_SETTINGS& Settings1, const AE_DSP_SETTINGS& Settings2); + + // reserved for future implementation + //static std::string GetAddonHomePath(); + //static std::string GetAddonSettingsFile(); +}; + +// reserved for future implementation +//class CADSPException : public CAddonException +//{ +// +//}; diff --git a/adsp.template/Addon/MVC/Interfaces/Controller/IController.hpp b/adsp.template/Addon/MVC/Interfaces/Controller/IController.hpp new file mode 100644 index 0000000..bd364d2 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/Controller/IController.hpp @@ -0,0 +1,38 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp" +#include "adsp.template/Addon/MVC/Interfaces/MVCObject.hpp" + +#include +#include + + +class IController : public MVCObject +{ +public: + IController(std::string Name, int ID, int ConnectionID) : + MVCObject(MVCObject::CONTROLLER_OBJECT, Name, ID, ConnectionID) + { + } +}; diff --git a/adsp.template/Addon/MVC/Interfaces/MVCObject.hpp b/adsp.template/Addon/MVC/Interfaces/MVCObject.hpp new file mode 100644 index 0000000..8507761 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/MVCObject.hpp @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.hpp" +#include "adsp.template/Addon/MessageSystem/Communication/ActorProtocol.h" + +#include + + +class MVCObject : public CMessageDispatcher +{ +public: + typedef enum { + INVALID_OBJECT = -1, + + MODEL_OBJECT, + VIEW_OBJECT, + CONTROLLER_OBJECT, + + MAX + }eMVCObjectType_t; + + MVCObject(eMVCObjectType_t Type, std::string Name, int ID, int ConnectionID) : + CMessageDispatcher(new CActorProtocol(Name, &m_InEvent, &m_OutEvent), Name, ID), + Type(Type), + ID(ID), + ConnectionID(ConnectionID) + { + } + + const int ID; + const int ConnectionID; + const eMVCObjectType_t Type; + + virtual int Create() = 0; + virtual void Destroy() = 0; + +protected: + CEvent m_InEvent; + CEvent m_OutEvent; +}; diff --git a/adsp.template/Addon/MVC/Interfaces/Model/IModel.hpp b/adsp.template/Addon/MVC/Interfaces/Model/IModel.hpp new file mode 100644 index 0000000..61e4115 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/Model/IModel.hpp @@ -0,0 +1,359 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp" +#include "adsp.template/Addon/MVC/Interfaces/MVCObject.hpp" +#include "adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp" + +#include "adsp.template/include/client.h" + +#include +#include + +using namespace ADDON; + +// TODO: shift method implementations into an cpp file +class IModel : public MVCObject +{ +private: // private declarations + typedef std::vector ParameterIDVector_t; + + class CParameterSort + { + public: + bool operator() (IParameter *Lhs, IParameter *Rhs) + { + return (Lhs->ID < Rhs->ID); + } + }; +public: + typedef std::vector ParameterVector_t; + + IModel(std::string Name, int ID, int ConnectionID) : + MVCObject(MVCObject::MODEL_OBJECT, Name, ID, ConnectionID) + { + m_ParameterIDMapping = nullptr; + m_MaxParameters = 0; + m_ParameterArray = nullptr; + } + + virtual ~IModel() + { + DestroyParameters(); + } + + + virtual int SetParameter(int ID, void *Data, size_t Size) + { + CSingleLock lock(m_ParameterLock); + if (m_MaxParameters <= 0) + { + return -1; + } + + int id = GetParameterID(ID); + if (id < 0) + { + return -1; + } + + return m_ParameterArray[id]->Set(ID, Data, Size); + } + + virtual int GetParameter(int ID, void *Data, size_t Size) + { + CSingleLock lock(m_ParameterLock); + if (m_MaxParameters <= 0) + { + return -1; + } + + int id = GetParameterID(ID); + if (id < 0) + { + return -1; + } + + return m_ParameterArray[id]->Get(ID, Data, Size); + } + + + virtual int SetParameterVector(ParameterVector_t &ParameterVector) + { + if (ParameterVector.size() <= 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to assign an empty parameter vector to model %s!", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + CSingleLock lock(m_ParameterLock); + if (m_ParameterVector.size() > 0) + { + for (int ii = 0; ii < (int)m_ParameterVector.size(); ii++) + { + ParameterVector.push_back(m_ParameterVector[ii]); + } + + m_ParameterIDs.clear(); + m_ParameterVector.clear(); + } + + // sort the Parameter IDs in a ascending consecutive order + sort(ParameterVector.begin(), ParameterVector.end(), m_Sort); + + int IDDistance = 1; + for (unsigned int ii = 1; ii < ParameterVector.size() && IDDistance == 1; ii++) + { + int diff = ParameterVector[ii]->ID - ParameterVector[ii - 1]->ID; + + if (diff <= 0) + {// Invalid input! Two equal Parameter IDs, which is not supported! + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to assign equal parameters to model %s!", __FUNCTION__, __LINE__, Name.c_str()); + + for (size_t ii = 0; ii < ParameterVector.size(); ii++) + { + if (ParameterVector[ii]) + { + delete ParameterVector[ii]; + ParameterVector[ii] = NULL; + } + } + + return false; + } + + if (diff > IDDistance) + { + IDDistance = diff; + } + } + + // if there is only one Parameter or the first one has an ID > 0 + // always adjust IDDistance + if ((ParameterVector.size() == 1 && ParameterVector[0]->ID > 0) || ParameterVector[0]->ID) + { + IDDistance = ParameterVector[0]->ID; + } + + // if IDDistance is greater 1, this object will need a LUT (Look Up Table) for its Parameter IDs + if (IDDistance != 1) + { + KODI->Log(LOG_DEBUG, "%s, %i, The model %s will use a LUT for Parameter assignment", __FUNCTION__, __LINE__, Name.c_str()); + m_ParameterIDs.reserve(ParameterVector.size()); + for (unsigned int ii = 0; ii < ParameterVector.size(); ii++) + { + m_ParameterIDs.push_back(ParameterVector[ii]->ID); + } + } + + KODI->Log(LOG_DEBUG, "%s, %i, The model %s has the following parameters: ", __FUNCTION__, __LINE__, Name.c_str()); + m_ParameterVector.reserve(ParameterVector.size()); + SocketVector_t sockets; + for (unsigned int ii = 0; ii < ParameterVector.size(); ii++) + { + KODI->Log(LOG_DEBUG, "%s, %i, Parameter: %s ID: %i", __FUNCTION__, __LINE__, ParameterVector[ii]->Name.c_str(), ParameterVector[ii]->ID); + sockets.push_back(dynamic_cast(new TSocketClassMethodCallback(this, &IModel::UpdateModel, ParameterVector[ii]->Name, ParameterVector[ii]->ID))); + m_ParameterVector.push_back(ParameterVector[ii]); + } + + if (!this->SetSockets(sockets)) + { + // TODO log error message + return -1; + } + + if (m_ParameterIDs.size() > 0) + { + m_ParameterIDMapping = m_ParameterIDs.data(); + } + else + { + m_ParameterIDMapping = nullptr; + } + + m_MaxParameters = m_ParameterVector.size(); + m_ParameterArray = m_ParameterVector.data(); + + return m_MaxParameters; + } + + virtual int AddParameter(IParameter *Parameter) + { + if (!Parameter) + { + return -1; + } + + int id = GetParameterID(Parameter->ID); + if (id != -1) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to add parameter %s with ID %i, which is already registered in model %s", __FUNCTION__, __LINE__, Parameter->Name.c_str(), Parameter->ID, Name.c_str()); + delete Parameter; + return false; + } + + if (!this->AddSocket(dynamic_cast(new TSocketClassMethodCallback(this, &IModel::UpdateModel, Parameter->Name, Parameter->ID)))) + { + return -1; + } + + CSingleLock lock(m_ParameterLock); + m_ParameterVector.push_back(Parameter); + + // sort the Socket IDs in a ascending consecutive order + sort(m_ParameterVector.begin(), m_ParameterVector.end(), m_Sort); + + // todo check order! + m_ParameterIDs.clear(); + m_ParameterIDs.reserve(m_ParameterVector.size()); + for (unsigned int ii = 0; ii < m_ParameterVector.size(); ii++) + { + m_ParameterIDs[ii] = m_ParameterVector[ii]->ID; + } + + KODI->Log(LOG_DEBUG, "%s, %i, Added parameter %s with ID %i to model %s", __FUNCTION__, __LINE__, Parameter->Name.c_str(), Parameter->ID, Name.c_str()); + + m_ParameterIDMapping = m_ParameterIDs.data(); + m_MaxParameters = m_ParameterVector.size(); + m_ParameterArray = m_ParameterVector.data(); + + return m_MaxParameters; + } + + virtual int RemoveParameter(int ID) + { + int id = GetParameterID(ID); + if (id < 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to remove a negative ParameterID from model %s!", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + CSingleLock lock(m_ParameterLock); + + ParameterVector_t::iterator iter = m_ParameterVector.begin() + id; + delete *iter; + *iter = NULL; + + this->RemoveSocket(m_ParameterVector[id]->ID); + m_ParameterVector.erase(m_ParameterVector.begin() + id); + m_ParameterIDs.erase(m_ParameterIDs.begin() + id); + + if (m_ParameterIDs.size() <= 0 || m_ParameterVector.size() <= 0) + { + + m_ParameterIDMapping = nullptr; + m_MaxParameters = 0; + m_ParameterArray = nullptr; + } + else + { + m_ParameterIDMapping = m_ParameterIDs.data(); + m_MaxParameters = m_ParameterVector.size(); + m_ParameterArray = m_ParameterVector.data(); + } + + KODI->Log(LOG_DEBUG, "%s, %i, Removed Parameter %s with ID %i", __FUNCTION__, __LINE__, m_ParameterArray[id]->Name.c_str(), m_ParameterArray[id]->ID); + + return 0; + } + + virtual int SaveParameters() + { + // todo implement XML sink + return 0; + } + +protected: // protected member methods + virtual void DestroyParameters() + { + CSingleLock lock(m_ParameterLock); + m_ParameterArray = NULL; + + for (size_t ii = 0; ii < m_ParameterVector.size(); ii++) + { + if (m_ParameterVector[ii]) + { + delete m_ParameterVector[ii]; + m_ParameterVector[ii] = NULL; + } + } + + m_ParameterVector.clear(); + } + +protected: // prototected member methods + virtual int UpdateModel(Message &Msg) + { + return this->SetParameter(Msg.signal, Msg.data, Msg.size); + } + +protected: // protected member variables + int *m_ParameterIDMapping; // TODO implement parameter ID LUT functionality + int m_MaxParameters; + IParameter **m_ParameterArray; + + ParameterVector_t m_ParameterVector; + ParameterIDVector_t m_ParameterIDs; + +private: + inline int GetParameterID(int ParameterID) + { + if (ParameterID < 0) + { + return -1; + } + + CSingleLock lock(m_ParameterLock); + if (m_MaxParameters == 0) + { + return -1; + } + + int id = ParameterID; + if (m_ParameterIDMapping) + { + bool ParameterIDFound = false; + for (int ii = 0; ii < m_MaxParameters; ii++) + { + if (m_ParameterIDMapping[ii] == ParameterID) + { + id = ii; + ParameterIDFound = true; + + break; + } + } + + if (!ParameterIDFound) + { + return -1; + } + } + + return id; + } + + CCriticalSection m_ParameterLock; + CParameterSort m_Sort; +}; diff --git a/adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp b/adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp new file mode 100644 index 0000000..1d7940e --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp @@ -0,0 +1,73 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include + + +class IParameter +{ +public: + IParameter(std::string Name, int ID, size_t Size) : + Name(Name), + ID(ID), + Size(Size) + { + } + + virtual ~IParameter() + { + } + + + const std::string Name; + const int ID; + const size_t Size; + + + int Set(int ID, void *Data, size_t Size) + { + if (!Data || ID != this->ID || Size != this->Size) + { + return -1; + } + + return Set(Data); + } + + int Get(int ID, void *Data, size_t Size) + { + if (!Data || ID != this->ID || Size != this->Size) + { + return -1; + } + + return Get(Data); + } + + virtual void* GetDataPtr() = 0; + +protected: // protected member methods + virtual int Set(void *Data) = 0; + virtual int Get(void *Data) = 0; +}; diff --git a/adsp.template/Addon/MVC/Interfaces/View/ActionIDs.hpp b/adsp.template/Addon/MVC/Interfaces/View/ActionIDs.hpp new file mode 100644 index 0000000..d95ba40 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/View/ActionIDs.hpp @@ -0,0 +1,275 @@ +#define ADDON_ACTION_NONE 0 +#define ADDON_ACTION_MOVE_LEFT 1 +#define ADDON_ACTION_MOVE_RIGHT 2 +#define ADDON_ACTION_MOVE_UP 3 +#define ADDON_ACTION_MOVE_DOWN 4 +#define ADDON_ACTION_PAGE_UP 5 +#define ADDON_ACTION_PAGE_DOWN 6 +#define ADDON_ACTION_SELECT_ITEM 7 +#define ADDON_ACTION_HIGHLIGHT_ITEM 8 +#define ADDON_ACTION_PARENT_DIR 9 +#define ADDON_ACTION_PREVIOUS_MENU 10 +#define ADDON_ACTION_SHOW_INFO 11 + +#define ADDON_ACTION_PAUSE 12 +#define ADDON_ACTION_STOP 13 +#define ADDON_ACTION_NEXT_ITEM 14 +#define ADDON_ACTION_PREV_ITEM 15 +#define ADDON_ACTION_FORWARD 16 //!< Can be used to specify specific action in a window, Playback control is handled in ADDON_ACTION_PLAYER_* +#define ADDON_ACTION_REWIND 17 //!< Can be used to specify specific action in a window, Playback control is handled in ADDON_ACTION_PLAYER_* + +#define ADDON_ACTION_SHOW_GUI 18 //!< toggle between GUI and movie or GUI and visualisation. +#define ADDON_ACTION_ASPECT_RATIO 19 //!< toggle quick-access zoom modes. Can b used in videoFullScreen.zml window id=2005 +#define ADDON_ACTION_STEP_FORWARD 20 //!< seek +1% in the movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_STEP_BACK 21 //!< seek -1% in the movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_BIG_STEP_FORWARD 22 //!< seek +10% in the movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_BIG_STEP_BACK 23 //!< seek -10% in the movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_SHOW_OSD 24 //!< show/hide OSD. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_SHOW_SUBTITLES 25 //!< turn subtitles on/off. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_NEXT_SUBTITLE 26 //!< switch to next subtitle of movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_SHOW_CODEC 27 //!< show debug info for VideoPlayer +#define ADDON_ACTION_NEXT_PICTURE 28 //!< show next picture of slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_PREV_PICTURE 29 //!< show previous picture of slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_OUT 30 //!< zoom in picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_IN 31 //!< zoom out picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_TOGGLE_SOURCE_DEST 32 //!< used to toggle between source view and destination view. Can be used in myfiles.xml window id=3 +#define ADDON_ACTION_SHOW_PLAYLIST 33 //!< used to toggle between current view and playlist view. Can b used in all mymusic xml files +#define ADDON_ACTION_QUEUE_ITEM 34 //!< used to queue a item to the playlist. Can b used in all mymusic xml files +#define ADDON_ACTION_REMOVE_ITEM 35 //!< not used anymore +#define ADDON_ACTION_SHOW_FULLSCREEN 36 //!< not used anymore +#define ADDON_ACTION_ZOOM_LEVEL_NORMAL 37 //!< zoom 1x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_1 38 //!< zoom 2x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_2 39 //!< zoom 3x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_3 40 //!< zoom 4x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_4 41 //!< zoom 5x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_5 42 //!< zoom 6x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_6 43 //!< zoom 7x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_7 44 //!< zoom 8x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_8 45 //!< zoom 9x picture during slideshow. Can b used in slideshow.xml window id=2007 +#define ADDON_ACTION_ZOOM_LEVEL_9 46 //!< zoom 10x picture during slideshow. Can b used in slideshow.xml window id=2007 + +#define ADDON_ACTION_CALIBRATE_SWAP_ARROWS 47 //!< select next arrow. Can b used in: settingsScreenCalibration.xml windowid=11 +#define ADDON_ACTION_CALIBRATE_RESET 48 //!< reset calibration to defaults. Can b used in: `settingsScreenCalibration.xml` windowid=11/settingsUICalibration.xml windowid=10 +#define ADDON_ACTION_ANALOG_MOVE 49 //!< analog thumbstick move. Can b used in: `slideshow.xml` windowid=2007/settingsScreenCalibration.xml windowid=11/settingsUICalibration.xml windowid=10 + //!< @note see also ADDON_ACTION_ANALOG_MOVE_X, ADDON_ACTION_ANALOG_MOVE_Y +#define ADDON_ACTION_ROTATE_PICTURE_CW 50 //!< rotate current picture clockwise during slideshow. Can be used in slideshow.xml window id=2007 +#define ADDON_ACTION_ROTATE_PICTURE_CCW 51 //!< rotate current picture counterclockwise during slideshow. Can be used in slideshow.xml window id=2007 + +#define ADDON_ACTION_SUBTITLE_DELAY_MIN 52 //!< Decrease subtitle/movie Delay. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_SUBTITLE_DELAY_PLUS 53 //!< Increase subtitle/movie Delay. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_AUDIO_DELAY_MIN 54 //!< Increase avsync delay. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_AUDIO_DELAY_PLUS 55 //!< Decrease avsync delay. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_AUDIO_NEXT_LANGUAGE 56 //!< Select next language in movie. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_CHANGE_RESOLUTION 57 //!< switch 2 next resolution. Can b used during screen calibration settingsScreenCalibration.xml windowid=11 + +#define REMOTE_0 58 //!< remote keys 0-9. are used by multiple windows +#define REMOTE_1 59 //!< for example in videoFullScreen.xml window id=2005 you can +#define REMOTE_2 60 //!< enter time (mmss) to jump to particular point in the movie +#define REMOTE_3 61 +#define REMOTE_4 62 //!< with spincontrols you can enter 3digit number to quickly set +#define REMOTE_5 63 //!< spincontrol to desired value +#define REMOTE_6 64 +#define REMOTE_7 65 +#define REMOTE_8 66 +#define REMOTE_9 67 + +#define ADDON_ACTION_PLAY 68 //!< Unused at the moment +#define ADDON_ACTION_SMALL_STEP_BACK 76 //!< jumps a few seconds back during playback of movie. Can b used in videoFullScreen.xml window id=2005 + +#define ADDON_ACTION_PLAYER_FORWARD 77 //!< FF in current file played. global action, can be used anywhere +#define ADDON_ACTION_PLAYER_REWIND 78 //!< RW in current file played. global action, can be used anywhere +#define ADDON_ACTION_PLAYER_PLAY 79 //!< Play current song. Unpauses song and sets playspeed to 1x. global action, can be used anywhere + +#define ADDON_ACTION_DELETE_ITEM 80 //!< delete current selected item. Can be used in myfiles.xml window id=3 and in myvideoTitle.xml window id=25 +#define ADDON_ACTION_COPY_ITEM 81 //!< copy current selected item. Can be used in myfiles.xml window id=3 +#define ADDON_ACTION_MOVE_ITEM 82 //!< move current selected item. Can be used in myfiles.xml window id=3 +#define ADDON_ACTION_TAKE_SCREENSHOT 85 //!< take a screenshot +#define ADDON_ACTION_RENAME_ITEM 87 //!< rename item + +#define ADDON_ACTION_VOLUME_UP 88 +#define ADDON_ACTION_VOLUME_DOWN 89 +#define ADDON_ACTION_VOLAMP 90 +#define ADDON_ACTION_MUTE 91 +#define ADDON_ACTION_NAV_BACK 92 +#define ADDON_ACTION_VOLAMP_UP 93 +#define ADDON_ACTION_VOLAMP_DOWN 94 + +#define ADDON_ACTION_CREATE_EPISODE_BOOKMARK 95 //!< Creates an episode bookmark on the currently playing video file containing more than one episode +#define ADDON_ACTION_CREATE_BOOKMARK 96 //!< Creates a bookmark of the currently playing video file + +#define ADDON_ACTION_CHAPTER_OR_BIG_STEP_FORWARD 97 //!< Goto the next chapter, if not available perform a big step forward +#define ADDON_ACTION_CHAPTER_OR_BIG_STEP_BACK 98 //!< Goto the previous chapter, if not available perform a big step back + +#define ADDON_ACTION_CYCLE_SUBTITLE 99 //!< switch to next subtitle of movie, but will not enable/disable the subtitles. Can be used in videoFullScreen.xml window id=2005 + +#define ADDON_ACTION_MOUSE_START 100 +#define ADDON_ACTION_MOUSE_LEFT_CLICK 100 +#define ADDON_ACTION_MOUSE_RIGHT_CLICK 101 +#define ADDON_ACTION_MOUSE_MIDDLE_CLICK 102 +#define ADDON_ACTION_MOUSE_DOUBLE_CLICK 103 +#define ADDON_ACTION_MOUSE_WHEEL_UP 104 +#define ADDON_ACTION_MOUSE_WHEEL_DOWN 105 +#define ADDON_ACTION_MOUSE_DRAG 106 +#define ADDON_ACTION_MOUSE_MOVE 107 +#define ADDON_ACTION_MOUSE_LONG_CLICK 108 +#define ADDON_ACTION_MOUSE_END 109 + +#define ADDON_ACTION_BACKSPACE 110 +#define ADDON_ACTION_SCROLL_UP 111 +#define ADDON_ACTION_SCROLL_DOWN 112 +#define ADDON_ACTION_ANALOG_FORWARD 113 +#define ADDON_ACTION_ANALOG_REWIND 114 + +#define ADDON_ACTION_MOVE_ITEM_UP 115 //!< move item up in playlist +#define ADDON_ACTION_MOVE_ITEM_DOWN 116 //!< move item down in playlist +#define ADDON_ACTION_CONTEXT_MENU 117 //!< pops up the context menu + +// stuff for virtual keyboard shortcuts +#define ADDON_ACTION_SHIFT 118 //!< stuff for virtual keyboard shortcuts +#define ADDON_ACTION_SYMBOLS 119 //!< stuff for virtual keyboard shortcuts +#define ADDON_ACTION_CURSOR_LEFT 120 //!< stuff for virtual keyboard shortcuts +#define ADDON_ACTION_CURSOR_RIGHT 121 //!< stuff for virtual keyboard shortcuts + +#define ADDON_ACTION_BUILT_IN_FUNCTION 122 + +#define ADDON_ACTION_SHOW_OSD_TIME 123 //!< displays current time, can be used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_ANALOG_SEEK_FORWARD 124 //!< seeks forward, and displays the seek bar. +#define ADDON_ACTION_ANALOG_SEEK_BACK 125 //!< seeks backward, and displays the seek bar. + +#define ADDON_ACTION_VIS_PRESET_SHOW 126 +#define ADDON_ACTION_VIS_PRESET_NEXT 128 +#define ADDON_ACTION_VIS_PRESET_PREV 129 +#define ADDON_ACTION_VIS_PRESET_LOCK 130 +#define ADDON_ACTION_VIS_PRESET_RANDOM 131 +#define ADDON_ACTION_VIS_RATE_PRESET_PLUS 132 +#define ADDON_ACTION_VIS_RATE_PRESET_MINUS 133 + +#define ADDON_ACTION_SHOW_VIDEOMENU 134 +#define ADDON_ACTION_ENTER 135 + +#define ADDON_ACTION_INCREASE_RATING 136 +#define ADDON_ACTION_DECREASE_RATING 137 + +#define ADDON_ACTION_NEXT_SCENE 138 //!< switch to next scene/cutpoint in movie +#define ADDON_ACTION_PREV_SCENE 139 //!< switch to previous scene/cutpoint in movie + +#define ADDON_ACTION_NEXT_LETTER 140 //!< jump through a list or container by letter +#define ADDON_ACTION_PREV_LETTER 141 + +#define ADDON_ACTION_JUMP_SMS2 142 //!< jump direct to a particular letter using SMS-style input +#define ADDON_ACTION_JUMP_SMS3 143 +#define ADDON_ACTION_JUMP_SMS4 144 +#define ADDON_ACTION_JUMP_SMS5 145 +#define ADDON_ACTION_JUMP_SMS6 146 +#define ADDON_ACTION_JUMP_SMS7 147 +#define ADDON_ACTION_JUMP_SMS8 148 +#define ADDON_ACTION_JUMP_SMS9 149 + +#define ADDON_ACTION_FILTER_CLEAR 150 +#define ADDON_ACTION_FILTER_SMS2 151 +#define ADDON_ACTION_FILTER_SMS3 152 +#define ADDON_ACTION_FILTER_SMS4 153 +#define ADDON_ACTION_FILTER_SMS5 154 +#define ADDON_ACTION_FILTER_SMS6 155 +#define ADDON_ACTION_FILTER_SMS7 156 +#define ADDON_ACTION_FILTER_SMS8 157 +#define ADDON_ACTION_FILTER_SMS9 158 + +#define ADDON_ACTION_FIRST_PAGE 159 +#define ADDON_ACTION_LAST_PAGE 160 + +#define ADDON_ACTION_AUDIO_DELAY 161 +#define ADDON_ACTION_SUBTITLE_DELAY 162 +#define ADDON_ACTION_MENU 163 + +#define ADDON_ACTION_SET_RATING 164 + +#define ADDON_ACTION_RECORD 170 + +#define ADDON_ACTION_PASTE 180 +#define ADDON_ACTION_NEXT_CONTROL 181 +#define ADDON_ACTION_PREV_CONTROL 182 +#define ADDON_ACTION_CHANNEL_SWITCH 183 +#define ADDON_ACTION_CHANNEL_UP 184 +#define ADDON_ACTION_CHANNEL_DOWN 185 +#define ADDON_ACTION_NEXT_CHANNELGROUP 186 +#define ADDON_ACTION_PREVIOUS_CHANNELGROUP 187 +#define ADDON_ACTION_PVR_PLAY 188 +#define ADDON_ACTION_PVR_PLAY_TV 189 +#define ADDON_ACTION_PVR_PLAY_RADIO 190 + +#define ADDON_ACTION_TOGGLE_FULLSCREEN 199 //!< switch 2 desktop resolution +#define ADDON_ACTION_TOGGLE_WATCHED 200 //!< Toggle watched status (videos) +#define ADDON_ACTION_SCAN_ITEM 201 //!< scan item +#define ADDON_ACTION_TOGGLE_DIGITAL_ANALOG 202 //!< switch digital <-> analog +#define ADDON_ACTION_RELOAD_KEYMAPS 203 //!< reloads CButtonTranslator's keymaps +#define ADDON_ACTION_GUIPROFILE_BEGIN 204 //!< start the GUIControlProfiler running + +#define ADDON_ACTION_TELETEXT_RED 215 //!< Teletext Color button Red to control TopText +#define ADDON_ACTION_TELETEXT_GREEN 216 //!< Teletext Color button Green to control TopText +#define ADDON_ACTION_TELETEXT_YELLOW 217 //!< Teletext Color button Yellow to control TopText +#define ADDON_ACTION_TELETEXT_BLUE 218 //!< Teletext Color button Blue to control TopText + +#define ADDON_ACTION_INCREASE_PAR 219 +#define ADDON_ACTION_DECREASE_PAR 220 + +#define ADDON_ACTION_VSHIFT_UP 227 //!< shift up video image in VideoPlayer +#define ADDON_ACTION_VSHIFT_DOWN 228 //!< shift down video image in VideoPlayer + +#define ADDON_ACTION_PLAYER_PLAYPAUSE 229 //!< Play/pause. If playing it pauses, if paused it plays. + +#define ADDON_ACTION_SUBTITLE_VSHIFT_UP 230 //!< shift up subtitles in VideoPlayer +#define ADDON_ACTION_SUBTITLE_VSHIFT_DOWN 231 //!< shift down subtitles in VideoPlayer +#define ADDON_ACTION_SUBTITLE_ALIGN 232 //!< toggle vertical alignment of subtitles + +#define ADDON_ACTION_FILTER 233 + +#define ADDON_ACTION_SWITCH_PLAYER 234 + +#define ADDON_ACTION_STEREOMODE_NEXT 235 +#define ADDON_ACTION_STEREOMODE_PREVIOUS 236 +#define ADDON_ACTION_STEREOMODE_TOGGLE 237 //!< turns 3d mode on/off +#define ADDON_ACTION_STEREOMODE_SELECT 238 +#define ADDON_ACTION_STEREOMODE_TOMONO 239 +#define ADDON_ACTION_STEREOMODE_SET 240 + +#define ADDON_ACTION_SETTINGS_RESET 241 +#define ADDON_ACTION_SETTINGS_LEVEL_CHANGE 242 + +#define ADDON_ACTION_TRIGGER_OSD 243 //!< show autoclosing OSD. Can b used in videoFullScreen.xml window id=2005 +#define ADDON_ACTION_INPUT_TEXT 244 +#define ADDON_ACTION_VOLUME_SET 245 +#define ADDON_ACTION_TOGGLE_COMMSKIP 246 + +#define ADDON_ACTION_TOUCH_TAP 401 //!< touch actions +#define ADDON_ACTION_TOUCH_TAP_TEN 410 //!< touch actions +#define ADDON_ACTION_TOUCH_LONGPRESS 411 //!< touch actions +#define ADDON_ACTION_TOUCH_LONGPRESS_TEN 420 //!< touch actions + +#define ADDON_ACTION_GESTURE_NOTIFY 500 +#define ADDON_ACTION_GESTURE_BEGIN 501 +#define ADDON_ACTION_GESTURE_ZOOM 502 //!< sendaction with point and currentPinchScale (fingers together < 1.0 -> fingers apart > 1.0) +#define ADDON_ACTION_GESTURE_ROTATE 503 +#define ADDON_ACTION_GESTURE_PAN 504 + +#define ADDON_ACTION_GESTURE_SWIPE_LEFT 511 +#define ADDON_ACTION_GESTURE_SWIPE_LEFT_TEN 520 +#define ADDON_ACTION_GESTURE_SWIPE_RIGHT 521 +#define ADDON_ACTION_GESTURE_SWIPE_RIGHT_TEN 530 +#define ADDON_ACTION_GESTURE_SWIPE_UP 531 +#define ADDON_ACTION_GESTURE_SWIPE_UP_TEN 540 +#define ADDON_ACTION_GESTURE_SWIPE_DOWN 541 +#define ADDON_ACTION_GESTURE_SWIPE_DOWN_TEN 550 +// 5xx is reserved for additional gesture actions +#define ADDON_ACTION_GESTURE_END 599 + +// other, non-gesture actions +#define ADDON_ACTION_ANALOG_MOVE_X 601 //!< analog thumbstick move, horizontal axis; see ADDON_ACTION_ANALOG_MOVE +#define ADDON_ACTION_ANALOG_MOVE_Y 602 //!< analog thumbstick move, vertical axis; see ADDON_ACTION_ANALOG_MOVE +//@} + +// The NOOP action can be specified to disable an input event. This is +// useful in user keyboard.xml etc to disable actions specified in the +// system mappings. ERROR action is used to play an error sound +#define ADDON_ACTION_ERROR 998 +#define ADDON_ACTION_NOOP 999 \ No newline at end of file diff --git a/adsp.template/Addon/MVC/Interfaces/View/IKodiGUIView.hpp b/adsp.template/Addon/MVC/Interfaces/View/IKodiGUIView.hpp new file mode 100644 index 0000000..87dd7f1 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/View/IKodiGUIView.hpp @@ -0,0 +1,152 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MVC/Interfaces/View/IView.hpp" +#include "adsp.template/include/client.h" +#include "adsp.template/Addon/MVC/Interfaces/View/ActionIDs.hpp" + +#include + + + +class IKodiGUIView : public IView +{ +public: + IKodiGUIView(std::string XMLFileName, bool ForceFallback, bool AsDialog, std::string Name, int ID, int ConnectionID, std::string DefaultSkin = "Confluence") : + IView(Name, ID, ConnectionID) + { + m_XMLFileName = XMLFileName; + m_DefaultSkin = DefaultSkin; + m_ForceFallback = ForceFallback; + m_AsDialog = AsDialog; + } + + virtual ~IKodiGUIView() + { + Destroy(); + } + + void Destroy() + { + if (m_window) + { + GUI->Window_destroy(m_window); + } + + m_window = NULL; + } + + int Create() + { + m_window = GUI->Window_create(m_XMLFileName.c_str(), + m_DefaultSkin.c_str(), + m_ForceFallback, + m_AsDialog); + if (!m_window) + { + KODI->Log(ADDON::LOG_ERROR, "%s, %i, Couldn't create IView!", __FUNCTION__, __LINE__); + return false; + } + + m_window->m_cbhdl = this; + m_window->CBOnInit = OnInitCB; + m_window->CBOnFocus = OnFocusCB; + m_window->CBOnClick = OnClickCB; + m_window->CBOnAction = OnActionCB; + + return true; + } + + bool Show() + { + if (!Create() || !m_window) + { + return false; + } + + return m_window->Show(); + } + + void Close() + { + if (m_window) + { + m_window->Close(); + } + + OnClose(); + + Destroy(); + } + + void DoModal() + { + if (!Create() || !m_window) + { + return; + } + + + m_window->DoModal(); + } + +private: + static bool OnClickCB(GUIHANDLE cbhdl, int controlId) + { + IKodiGUIView *dialog = static_cast(cbhdl); + return dialog->OnClick(controlId); + } + + static bool OnFocusCB(GUIHANDLE cbhdl, int controlId) + { + IKodiGUIView *dialog = static_cast(cbhdl); + return dialog->OnFocus(controlId); + } + + static bool OnInitCB(GUIHANDLE cbhdl) + { + IKodiGUIView *dialog = static_cast(cbhdl); + return dialog->OnInit(); + } + + static bool OnActionCB(GUIHANDLE cbhdl, int actionId) + { + IKodiGUIView *dialog = static_cast(cbhdl); + return dialog->OnAction(actionId); + } + +protected: + CAddonGUIWindow *m_window; // window handle + +private: // private virtual methods + virtual bool OnInit() = 0; + virtual bool OnClick(int controlId) = 0; + virtual bool OnFocus(int controlId) = 0; + virtual bool OnAction(int actionId) = 0; + virtual void OnClose() = 0; + + std::string m_XMLFileName; + bool m_ForceFallback; + bool m_AsDialog; + std::string m_DefaultSkin; +}; diff --git a/adsp.template/Addon/MVC/Interfaces/View/IView.hpp b/adsp.template/Addon/MVC/Interfaces/View/IView.hpp new file mode 100644 index 0000000..6e44145 --- /dev/null +++ b/adsp.template/Addon/MVC/Interfaces/View/IView.hpp @@ -0,0 +1,36 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MVC/Interfaces/MVCObject.hpp" + +#include "adsp.template/include/client.h" + + +class IView : public MVCObject +{ +public: + IView(std::string Name, int ID, int ConnectionID) : + MVCObject(MVCObject::VIEW_OBJECT, Name, ID, ConnectionID) + { + } +}; diff --git a/adsp.template/Addon/MVC/Model/TParameter.hpp b/adsp.template/Addon/MVC/Model/TParameter.hpp new file mode 100644 index 0000000..df31a55 --- /dev/null +++ b/adsp.template/Addon/MVC/Model/TParameter.hpp @@ -0,0 +1,64 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MVC/Interfaces/Model/IParameter.hpp" + +#include + + +#define CreateTParameter(Type, StringClass, ID) dynamic_cast(new TParameter(StringClass::ToString(StringClass::ID), StringClass::ID)) + + +template +class TParameter : public IParameter +{ +public: + TParameter(std::string Name, int ID) : + IParameter(Name, ID, sizeof(T)) + { + memset(&m_Data, 0, this->Size); + } + + virtual void* GetDataPtr() + { + return (void*)&m_Data; + } + + +protected: // protected member variables + virtual int Set(void *Data) + { + memcpy(&this->m_Data, Data, this->Size); + + return 0; + } + + virtual int Get(void *Data) + { + memcpy(Data, &this->m_Data, this->Size); + + return 0; + } + + T m_Data; +}; diff --git a/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.cpp b/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.cpp new file mode 100644 index 0000000..fdeeea7 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.cpp @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + + +#include "ActorProtocol.h" +#include "Message.hpp" + + +CActorProtocol::~CActorProtocol() +{ + Message *msg; + Purge(); + while (!freeMessageQueue.empty()) + { + msg = freeMessageQueue.front(); + freeMessageQueue.pop(); + delete msg; + } +} + +Message *CActorProtocol::GetMessage() +{ + Message *msg; + + CSingleLock lock(criticalSection); + + if (!freeMessageQueue.empty()) + { + msg = freeMessageQueue.front(); + freeMessageQueue.pop(); + } + else + msg = new Message(); + + msg->isSync = false; + msg->isSyncFini = false; + msg->isSyncTimeout = false; + msg->event = NULL; + msg->data = NULL; + msg->payloadSize = 0; + msg->replyMessage = NULL; + msg->origin = this; + + return msg; +} + +void CActorProtocol::ReturnMessage(Message *msg) +{ + CSingleLock lock(criticalSection); + + freeMessageQueue.push(msg); +} + +bool CActorProtocol::SendOutMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) +{ + Message *msg; + if (outMsg) + msg = outMsg; + else + msg = GetMessage(); + + msg->signal = signal; + msg->isOut = true; + + if (data) + { + msg->size = size; + if (size > MSG_INTERNAL_BUFFER_SIZE) + msg->data = new uint8_t[size]; + else + msg->data = msg->buffer; + memcpy(msg->data, data, size); + } + + { CSingleLock lock(criticalSection); + outMessages.push(msg); + } + containerOutEvent->Set(); + + return true; +} + +bool CActorProtocol::SendInMessage(int signal, void *data /* = NULL */, int size /* = 0 */, Message *outMsg /* = NULL */) +{ + Message *msg; + if (outMsg) + msg = outMsg; + else + msg = GetMessage(); + + msg->signal = signal; + msg->isOut = false; + + if (data) + { + msg->size = size; + if (size > MSG_INTERNAL_BUFFER_SIZE) + { + msg->data = new uint8_t[size]; + } + else + { + msg->data = msg->buffer; + } + memcpy(msg->data, data, size); + } + + + { CSingleLock lock(criticalSection); + inMessages.push(msg); + } + containerInEvent->Set(); + + return true; +} + + +bool CActorProtocol::SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data /* = NULL */, int size /* = 0 */) +{ + Message *msg = GetMessage(); + msg->isOut = true; + msg->isSync = true; + msg->event = new CEvent; + msg->event->Reset(); + SendOutMessage(signal, data, size, msg); + + if (!msg->event->WaitMSec(timeout)) + { + msg->origin->Lock(); + if (msg->replyMessage) + *retMsg = msg->replyMessage; + else + { + *retMsg = NULL; + msg->isSyncTimeout = true; + } + msg->origin->Unlock(); + } + else + *retMsg = msg->replyMessage; + + msg->Release(); + + if (*retMsg) + return true; + else + return false; +} + +bool CActorProtocol::ReceiveOutMessage(Message **msg) +{ + CSingleLock lock(criticalSection); + + if (outMessages.empty() || outDefered) + return false; + + *msg = outMessages.front(); + outMessages.pop(); + + return true; +} + +bool CActorProtocol::ReceiveInMessage(Message **msg) +{ + CSingleLock lock(criticalSection); + + if (inMessages.empty() || inDefered) + return false; + + *msg = inMessages.front(); + inMessages.pop(); + + return true; +} + + +void CActorProtocol::Purge() +{ + Message *msg; + + while (ReceiveInMessage(&msg)) + msg->Release(); + + while (ReceiveOutMessage(&msg)) + msg->Release(); +} + +void CActorProtocol::PurgeIn(int signal) +{ + Message *msg; + std::queue msgs; + + CSingleLock lock(criticalSection); + + while (!inMessages.empty()) + { + msg = inMessages.front(); + inMessages.pop(); + if (msg->signal != signal) + msgs.push(msg); + } + while (!msgs.empty()) + { + msg = msgs.front(); + msgs.pop(); + inMessages.push(msg); + } +} + +void CActorProtocol::PurgeOut(int signal) +{ + Message *msg; + std::queue msgs; + + CSingleLock lock(criticalSection); + + while (!outMessages.empty()) + { + msg = outMessages.front(); + outMessages.pop(); + if (msg->signal != signal) + msgs.push(msg); + } + while (!msgs.empty()) + { + msg = msgs.front(); + msgs.pop(); + outMessages.push(msg); + } +} diff --git a/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.h b/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.h new file mode 100644 index 0000000..e01cac9 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/ActorProtocol.h @@ -0,0 +1,64 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "KodiThreads/threads/Thread.h" +#include +#include "memory.h" + +#include "adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp" + + +class CActorProtocol : public IProtocol +{ +public: + CActorProtocol(std::string Name, CEvent* InEvent = NULL, CEvent *OutEvent = NULL) : + IProtocol(Name, InEvent, OutEvent) + {} + + virtual ~CActorProtocol(); + + // get a message from freeMessageQueue or create a new one + virtual Message *GetMessage(); + // return a message and store it in freeMessageQueue + virtual void ReturnMessage(Message *msg); + // send an out message and store a pointer in outMessages + virtual bool SendOutMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); + // send an in message and store a pointer in inMessages + virtual bool SendInMessage(int signal, void *data = NULL, int size = 0, Message *outMsg = NULL); + // send an synchronuous out message with a time out value + virtual bool SendOutMessageSync(int signal, Message **retMsg, int timeout, void *data = NULL, int size = 0); + virtual bool ReceiveOutMessage(Message **msg); + virtual bool ReceiveInMessage(Message **msg); + + // empty in- and out-message queues + virtual void Purge(); + // empty in-message queue except the message with the ID stored in signal + virtual void PurgeIn(int Signal); + // empty out-message queue except the message with the ID stored in signal + virtual void PurgeOut(int Signal); + +protected: + std::queue outMessages; // thread safe out message queue + std::queue inMessages; // thread safe in message queue + std::queue freeMessageQueue; // thread safe free message queue that are used for new messages +}; diff --git a/adsp.template/Addon/MessageSystem/Communication/Message.cpp b/adsp.template/Addon/MessageSystem/Communication/Message.cpp new file mode 100644 index 0000000..39a64b7 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/Message.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include + +#include "Message.hpp" +#include "Addon/MessageSystem/Interfaces/IProtocol.hpp" + + +void Message::Release() +{ + bool skip; + origin->Lock(); + skip = isSync ? !isSyncFini : false; + isSyncFini = true; + origin->Unlock(); + + if (skip) + return; + + // free data buffer + if (data != buffer) + delete[] data; + + // delete event in case of sync message + if (event) + delete event; + + origin->ReturnMessage(this); +} + +bool Message::Reply(int sig, void *data /* = NULL*/, int size /* = 0 */) +{ + if (!isSync) + { + if (isOut) + return origin->SendInMessage(sig, data, size); + else + return origin->SendOutMessage(sig, data, size); + } + + origin->Lock(); + + if (!isSyncTimeout) + { + Message *msg = origin->GetMessage(); + msg->signal = sig; + msg->isOut = !isOut; + replyMessage = msg; + if (data) + { + if (size > MSG_INTERNAL_BUFFER_SIZE) + msg->data = new uint8_t[size]; + else + msg->data = msg->buffer; + memcpy(msg->data, data, size); + } + } + + origin->Unlock(); + + if (event) + event->Set(); + + return true; +} diff --git a/adsp.template/Addon/MessageSystem/Communication/Message.hpp b/adsp.template/Addon/MessageSystem/Communication/Message.hpp new file mode 100644 index 0000000..2749be5 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/Message.hpp @@ -0,0 +1,72 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "KodiThreads/threads/Thread.h" +#include "adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp" + + +#define MSG_INTERNAL_BUFFER_SIZE 32 + +class Message +{ + friend class IProtocol; + +public: + Message() + { + signal = -1; + isSync = false; + isSyncFini = false; + isOut = false; + isSyncTimeout = false; + payloadSize = MSG_INTERNAL_BUFFER_SIZE; + size = MSG_INTERNAL_BUFFER_SIZE; + memset(buffer, 0, sizeof(uint8_t)*MSG_INTERNAL_BUFFER_SIZE); + data = buffer; + replyMessage = nullptr; + + origin = nullptr; + destiny = nullptr; + + event = nullptr; + }; + + int signal; + bool isSync; + bool isSyncFini; + bool isOut; + bool isSyncTimeout; + int payloadSize; + int size; + uint8_t buffer[MSG_INTERNAL_BUFFER_SIZE]; + uint8_t *data; + Message *replyMessage; + + IProtocol *origin; // address to sender Protocol instance + IProtocol *destiny; // address to receiver Protocol instance + + CEvent *event; + + void Release(); + bool Reply(int sig, void *data = NULL, int size = 0); +}; diff --git a/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.cpp b/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.cpp new file mode 100644 index 0000000..fd6dc4b --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.cpp @@ -0,0 +1,545 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "Addon/MessageSystem/Communication/MessageDispatcher.hpp" + +#include "include/client.h" + +#include + +using namespace std; +using namespace ADDON; + + +int CMessageDispatcher::m_UniqueIDCount = 0; + + +CMessageDispatcher::CMessageDispatcher(IProtocol *Protocol, std::string Name, int ID/*=-1*/, bool IsMaster/* = false*/) : + ID(++m_UniqueIDCount), + Name(Name) +{ + if (!Protocol) + { + // TODO throw exception! + } + + KODI->Log(LOG_DEBUG, "%s, %i, Creating message handler %s with unique ID %i", __FUNCTION__, __LINE__, Name.c_str(), ID); + + m_Protocol = Protocol; + + { + CSingleLock socketLock(m_SocketLock); + m_MaxSockets = 0; + m_SocketIDLUT = NULL; + m_SocketArray = NULL; + } + + CSingleLock lock(m_ConnectionLock); + m_MaxConnectedDispatchers = 0; + m_DispatcherIDLUT = NULL; + m_DispatcherArray = NULL; + + if (IsMaster) + { + m_Master = this; + } + else + { + m_Master = NULL; + } +} + +CMessageDispatcher::~CMessageDispatcher() +{ + KODI->Log(LOG_DEBUG, "%s, %i, Destroying message handler %s with unique ID %i", __FUNCTION__, __LINE__, Name.c_str(), ID); + + { + CSingleLock lock(m_ConnectionLock); + if (m_Master != this && m_Master) + { + DisconnectDispatcher(this); + } + } + + DestroySockets(); + + if (m_Protocol) + { + delete m_Protocol; + m_Protocol = NULL; + } +} + + +bool CMessageDispatcher::SetSockets(SocketVector_t &SocketVector) +{ + if (SocketVector.size() <= 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to assign an empty Socket vector to message handler %s!", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + CSingleLock lock(m_SocketLock); + if (m_Sockets.size() > 0) + { + for (int ii = 0; ii < (int)m_Sockets.size(); ii++) + { + SocketVector.push_back(m_Sockets[ii]); + } + + m_SocketIDs.clear(); + m_Sockets.clear(); + } + + // sort the Socket IDs in a ascending consecutive order + sort(SocketVector.begin(), SocketVector.end(), m_SocketSort); + + int IDDistance = 1; + for (unsigned int ii = 1; ii < SocketVector.size() && IDDistance == 1; ii++) + { + int diff = SocketVector[ii]->ID - SocketVector[ii - 1]->ID; + + if (diff <= 0) + {// Invalid input! Two equal Socket IDs, which is not supported! + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to assign equal Sockets to the message handler %s!", __FUNCTION__, __LINE__, Name.c_str()); + + for (size_t ii = 0; ii < SocketVector.size(); ii++) + { + if (SocketVector[ii]) + { + delete SocketVector[ii]; + SocketVector[ii] = NULL; + } + } + + return false; + } + + if (diff > IDDistance) + { + IDDistance = diff; + } + } + + // if there is only one Socket or the first one has an ID > 0 + // always adjust IDDistance + if ((SocketVector.size() == 1 && SocketVector[0]->ID > 0) || SocketVector[0]->ID) + { + IDDistance = SocketVector[0]->ID; + } + + // if IDDistance is greater 1, this object will need a LUT (Look Up Table) for its Socket IDs + if (IDDistance != 1) + { + KODI->Log(LOG_DEBUG, "%s, %i, The message handler %s will use a LUT for Socket assignment", __FUNCTION__, __LINE__, Name.c_str()); + m_SocketIDs.reserve(SocketVector.size()); + for (unsigned int ii = 0; ii < SocketVector.size(); ii++) + { + m_SocketIDs.push_back(SocketVector[ii]->ID); + } + } + + KODI->Log(LOG_DEBUG, "%s, %i, The message handler %s has the following Sockets: ", __FUNCTION__, __LINE__, Name.c_str()); + m_Sockets.reserve(SocketVector.size()); + for (unsigned int ii = 0; ii < SocketVector.size(); ii++) + { + KODI->Log(LOG_DEBUG, "%s, %i, Socket: %s ID: %i", __FUNCTION__, __LINE__, SocketVector[ii]->Name.c_str(), SocketVector[ii]->ID); + m_Sockets.push_back(SocketVector[ii]); + } + + if (m_SocketIDs.size() > 0) + { + m_SocketIDLUT = m_SocketIDs.data(); + } + else + { + m_SocketIDLUT = nullptr; + } + m_MaxSockets = m_Sockets.size(); + m_SocketArray = m_Sockets.data(); + + return true; +} + +bool CMessageDispatcher::AddSocket(ISocket *Socket) +{ + if (!Socket) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to add an invalid socket to message handler %s!", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + int id = GetSocketID(Socket->ID); + if (id != -1) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to add socket %s with ID %i, which is already available at message dispatcher %s", __FUNCTION__, __LINE__, Socket->Name.c_str(), Socket->ID, Name.c_str()); + delete Socket; + return false; + } + + CSingleLock lock(m_SocketLock); + m_Sockets.push_back(Socket); + + // sort the Socket IDs in a ascending consecutive order + sort(m_Sockets.begin(), m_Sockets.end(), m_SocketSort); + + // todo check order! + m_SocketIDs.clear(); + m_SocketIDs.reserve(m_Sockets.size()); + for (unsigned int ii = 0; ii < m_Sockets.size(); ii++) + { + m_SocketIDs[ii] = m_Sockets[ii]->ID; + } + + KODI->Log(LOG_DEBUG, "%s, %i, Added socket %s with ID %i to message handler %s", __FUNCTION__, __LINE__, Socket->Name.c_str(), Socket->ID, Name.c_str()); + + m_SocketIDLUT = m_SocketIDs.data(); + m_MaxSockets = m_Sockets.size(); + m_SocketArray = m_Sockets.data(); + + return false; +} + +bool CMessageDispatcher::RemoveSocket(int SocketID) +{ + int id = GetSocketID(SocketID); + if (id < 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to remove a negative SocketID from message handler %s!", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + CSingleLock lock(m_SocketLock); + + SocketVector_t::iterator iter = m_Sockets.begin() + id; + delete *iter; + *iter = NULL; + + m_Sockets.erase(m_Sockets.begin() + id); + m_SocketIDs.erase(m_SocketIDs.begin() + id); + + if (m_SocketIDs.size() <= 0 || m_Sockets.size() <= 0) + { + + m_SocketIDLUT = NULL; + m_MaxSockets = 0; + m_SocketArray = NULL; + } + else + { + m_SocketIDLUT = m_SocketIDs.data(); + m_MaxSockets = m_Sockets.size(); + m_SocketArray = m_Sockets.data(); + KODI->Log(LOG_DEBUG, "%s, %i, Removed Socket %s with ID %i", __FUNCTION__, __LINE__, m_SocketArray[id]->Name.c_str(), m_SocketArray[id]->ID); + } + + return true; +} + + +bool CMessageDispatcher::SendMsg(int SocketID, int DispatcherID/* = -1*/) +{ + CSingleLock socketLock(m_SocketLock); + int socketIdx = GetSocketID(SocketID); + if(socketIdx < 0) + { + return false; + } + + CSingleLock socketArrayLock(m_SocketArray[socketIdx]->Lock); + if (!m_SocketArray[socketIdx]->HasUpdated) + { + return false; + } + + CSingleLock lock(m_ConnectionLock); + if (DispatcherID < 0) + { // send this Socket ID to all connected Dispatchers + for (int ii = 0; ii < m_MaxConnectedDispatchers; ii++) + {// TODO: check return value + m_DispatcherArray[ii]->m_Protocol->SendInMessage(m_SocketArray[socketIdx]->ID, + m_SocketArray[socketIdx]->Get(), + m_SocketArray[socketIdx]->Size); + } + + return true; + } + else + { + int DispatcherIdx = GetDispatcherIdx(DispatcherID); + if (DispatcherIdx < 0) + { + return false; + } + + m_SocketArray[socketIdx]->HasUpdated = false; + return m_DispatcherArray[DispatcherIdx]->m_Protocol->SendInMessage(m_SocketArray[socketIdx]->ID, + m_SocketArray[socketIdx]->Get(), + m_SocketArray[socketIdx]->Size); + } + + return false; +} + +bool CMessageDispatcher::SendMsg(void *Data, size_t Size, int SocketID, int DispatcherID/* = -1*/) +{ + CSingleLock lock(m_ConnectionLock); + + if (DispatcherID < 0) + {// send message to all connected dispatchers + for (int ii = 0; ii < m_MaxConnectedDispatchers; ii++) + {// TODO: check return value + m_DispatcherArray[ii]->m_Protocol->SendInMessage(SocketID, Data, Size); + } + + return true; + } + else + { + int dispatcherIdx = GetDispatcherIdx(DispatcherID); + if (dispatcherIdx < 0) + { + return false; + } + + return m_DispatcherArray[dispatcherIdx]->m_Protocol->SendInMessage(SocketID, Data, Size); + } + + return false; +} + + +bool CMessageDispatcher::ConnectDispatcher(CMessageDispatcher *Dispatcher) +{ + if (!Dispatcher) + { + return false; + } + + { + CSingleLock lock(m_ConnectionLock); + + m_Dispatchers.push_back(Dispatcher); + m_DispatcherIDs.push_back(Dispatcher->ID); + + m_DispatcherIDLUT = m_DispatcherIDs.data(); + m_DispatcherArray = m_Dispatchers.data(); + m_MaxConnectedDispatchers = m_Dispatchers.size(); + + CSingleLock parterLock(Dispatcher->m_ConnectionLock); + if (m_Master == this) + { + Dispatcher->m_Master = this; + KODI->Log(LOG_DEBUG, "%s, %i, Dispatcher %s connected to master dispatcher %s", __FUNCTION__, __LINE__, Dispatcher->Name.c_str(), Name.c_str()); + } + else + { + KODI->Log(LOG_NOTICE, "%s, %i, Dispatcher %s connected to non master dispatcher %s! The message system might not work correctly!", __FUNCTION__, __LINE__, Dispatcher->Name.c_str(), Name.c_str()); + } + } + + return true; +} + +bool CMessageDispatcher::DisconnectDispatcher(CMessageDispatcher *Dispatcher) +{ + if (!Dispatcher) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! Tried to disconnect invalid dispatcher at dispatcher %s", __FUNCTION__, __LINE__, Name.c_str()); + return false; + } + + CSingleLock lock(m_ConnectionLock); + if (m_Dispatchers.size() <= 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to disconnect dispatcher %s with ID %i from dispatcher %s without any connected dispatchers!", __FUNCTION__, __LINE__, Dispatcher->Name.c_str(), Dispatcher->ID, Name.c_str()); + return false; + } + + int dispatcherIdx = GetDispatcherIdx(Dispatcher->ID); + if (dispatcherIdx < 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! The dispatcher %s with ID %i was not connected to dispatcher %s", __FUNCTION__, __LINE__, Dispatcher->Name.c_str(), Dispatcher->ID, Name.c_str()); + return false; + } + + m_Dispatchers.erase(m_Dispatchers.begin() + dispatcherIdx); + m_DispatcherIDs.erase(m_DispatcherIDs.begin() + dispatcherIdx); + + if(m_Dispatchers.size() > 0) + { + m_DispatcherIDLUT = m_DispatcherIDs.data(); + m_DispatcherArray = m_Dispatchers.data(); + m_MaxConnectedDispatchers = m_Dispatchers.size(); + } + else + { + m_DispatcherIDLUT = NULL; + m_DispatcherArray = NULL; + m_MaxConnectedDispatchers = 0; + } + + KODI->Log(LOG_DEBUG, "%s, %i, Disconnected dispatcher %s with ID %i from dispatcher %s", __FUNCTION__, __LINE__, Dispatcher->Name.c_str(), Dispatcher->ID, Name.c_str()); + + CSingleLock parterLock(Dispatcher->m_ConnectionLock); + Dispatcher->m_Master = NULL; + + return true; +} + +void CMessageDispatcher::ProcessMessage() +{ + Message *msg = NULL; + if (m_Protocol && m_Protocol->ReceiveInMessage(&msg)) + { + int SocketID = GetSocketID(msg->signal); + if (SocketID >= 0) + { + CSingleLock lock(m_SocketLock); + int err = m_SocketArray[SocketID]->Set(*msg); + if (err != 0) + { + // TODO reply with error + } + } + else + { + // TODO reply with error + } + + msg->Release(); + msg = NULL; + } +} + +void CMessageDispatcher::ProcessMessages() +{ + Message *msg = NULL; + while (m_Protocol && m_Protocol->ReceiveInMessage(&msg)) + { + int socketID = GetSocketID(msg->signal); + if (socketID >= 0) + { + CSingleLock lock(m_SocketLock); + int err = m_SocketArray[socketID]->Set(*msg); + if (err != 0) + { + // TODO reply with error + } + } + else + { + // TODO reply with error + } + + msg->Release(); + msg = NULL; + } +} + +void CMessageDispatcher::ProcessConnectedMessage() +{ + CSingleLock lock(m_ConnectionLock); + + for (int ii = 0; ii < m_MaxConnectedDispatchers; ii++) + { + m_DispatcherArray[ii]->ProcessMessage(); + } +} + +void CMessageDispatcher::ProcessConnectedMessages() +{ + CSingleLock lock(m_ConnectionLock); + + for (int ii = 0; ii < m_MaxConnectedDispatchers; ii++) + { + m_DispatcherArray[ii]->ProcessMessages(); + } +} +//bool CMessageDispatcher::RemoveDispatcher(CMessageDispatcher *Dispatcher) +//{ +// if (!Dispatcher) +// { +// return false; +// } +// +// int DispatcherID = GetDispatcherIdx(Dispatcher->ID); +// if (DispatcherID < 0) +// { +// return false; +// } +// +// { +// CSingleLock lock(m_ConnectionLock); +// m_Dispatchers.erase(m_Dispatchers.begin() + DispatcherID); +// m_DispatcherIDs.erase(m_DispatcherIDs.begin() + DispatcherID); +// +// m_DispatcherIDLUT = m_DispatcherIDs.data(); +// m_DispatcherArray = m_Dispatchers.data(); +// m_MaxConnectedDispatchers = m_Dispatchers.size(); +// } +// +// return true; +//} + + +void CMessageDispatcher::DestroySockets() +{ + CSingleLock lock(m_SocketLock); + + if (m_Sockets.size() > 0) + { + for (SocketVector_t::iterator iter = m_Sockets.begin(); iter != m_Sockets.end(); ++iter) + { + if (*iter) + { + delete *iter; + } + + *iter = NULL; + } + + m_Sockets.clear(); + m_SocketArray = NULL; + + m_SocketIDs.clear(); + m_SocketIDLUT = NULL; + } +} + + +bool CMessageDispatcher::ReceiveMsg(Message *Msg) +{ + if (!Msg) + { + return false; + } + + if (!m_Protocol->SendInMessage(Msg->signal, Msg->data, Msg->size)) + { + return false; + } + + //TODO: find a better solution to release or store the message here! + Msg->Release(); + return true; +} diff --git a/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.hpp b/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.hpp new file mode 100644 index 0000000..f1289f4 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Communication/MessageDispatcher.hpp @@ -0,0 +1,174 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include + +#include "KodiThreads/threads/CriticalSection.h" +#include "KodiThreads/threads/SingleLock.h" + +#include "adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp" +#include "adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp" + + +class CMessageDispatcher +{ + friend class CMessageDispatcher; + +public: + CMessageDispatcher(IProtocol *Protocol, std::string Name, int ID = -1, bool IsMaster = false); + virtual ~CMessageDispatcher(); + + bool SetSockets(SocketVector_t &SocketVector); + bool AddSocket(ISocket *Socket); + bool RemoveSocket(int SocketID); + + bool ConnectDispatcher(CMessageDispatcher *Dispatcher); + bool DisconnectDispatcher(CMessageDispatcher *Dispatcher); + + bool SendMsg(int SocketID, int DispatcherID = -1); + bool SendMsg(void *Data, size_t Size, int SocketID, int DispatcherID = -1); + bool ReceiveMsg(Message *Msg); + + void ProcessMessage(); + void ProcessMessages(); + void ProcessConnectedMessage(); + void ProcessConnectedMessages(); + + const std::string Name; // Custom name for this object + const int ID; // assigned unique member ID for message assignment + +private: + void DestroySockets(); + + inline int GetSocketID(int SocketID) + { + if (SocketID < 0) + { + return -1; + } + + CSingleLock lock(m_SocketLock); + if (m_MaxSockets == 0) + { + return -1; + } + + int id = SocketID; + if (m_SocketIDLUT) + { + bool SocketIDFound = false; + for (int ii = 0; ii < m_MaxSockets; ii++) + { + if (m_SocketIDLUT[ii] == SocketID) + { + id = ii; + SocketIDFound = true; + + break; + } + } + + if (!SocketIDFound) + { + return -1; + } + } + + return id; + } + + inline int GetDispatcherIdx(int DispatcherID) + { + int idx = -1; + + { + CSingleLock lock(m_ConnectionLock); + bool DispatcherFound = false; + + if(m_DispatcherIDLUT) + { + for (int ii = 0; ii < m_MaxConnectedDispatchers; ii++) + { + if (m_DispatcherIDLUT[ii] == DispatcherID) + { + idx = ii; + DispatcherFound = true; + + break; + } + } + } + else + { + DispatcherFound = true; + idx = DispatcherID; + } + + if (!DispatcherFound) + { + return -1; + } + } + + return idx; + } + + class CSocketSort + { + public: + bool operator() (ISocket *Lhs, ISocket *Rhs) + { + return (Lhs->ID < Rhs->ID); + } + }; + + + // specific member variables for message processing + CCriticalSection m_ConnectionLock; + + int m_MaxConnectedDispatchers; + int *m_DispatcherIDLUT; + CMessageDispatcher **m_DispatcherArray; + + std::vector m_DispatcherIDs; + std::vector m_Dispatchers; + CMessageDispatcher *m_Master; + + + // specific member variables for Socket processing + CCriticalSection m_SocketLock; + + int m_MaxSockets; + int *m_SocketIDLUT; + ISocket **m_SocketArray; + + std::vector m_SocketIDs; + SocketVector_t m_Sockets; + CSocketSort m_SocketSort; + + // specific member variables protocol handling + IProtocol *m_Protocol; + + + static int m_UniqueIDCount; // static member variable for object counting +}; diff --git a/adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp b/adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp new file mode 100644 index 0000000..febd694 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Interfaces/IProtocol.hpp @@ -0,0 +1,93 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include + +#include "KodiThreads/threads/Thread.h" + +class Message; + + +class IProtocol +{ +public: + IProtocol(std::string &Name, CEvent* InEvent, CEvent *OutEvent) : + portName(Name) + { + inDefered = false; + outDefered = false; + + containerInEvent = InEvent; + containerOutEvent = OutEvent; + }; + + virtual ~IProtocol() {} + + // ??? + void DeferIn(bool Value) { inDefered = Value; }; + + // ??? + void DeferOut(bool Value) { outDefered = Value; }; + + // set thread safe lock + void Lock() { criticalSection.lock(); }; + + // unset thread safe lock + void Unlock() { criticalSection.unlock(); }; + + + + // protocol port name + const std::string portName; + + +// abstract methods + // return a message and store it in freeMessageQueue + virtual void ReturnMessage(Message *Msg) = 0; + // send an out message and store a pointer in outMessages + virtual bool SendOutMessage(int Signal, void *Data = NULL, int Size = 0, Message *OutMsg = NULL) = 0; + // send an in message and store a pointer in inMessages + virtual bool SendInMessage(int Signal, void *Data = NULL, int Size = 0, Message *InMsg = NULL) = 0; + // send an synchronuous out message with a time out value + virtual bool SendOutMessageSync(int Signal, Message **RetMsg, int Timeout, void *Data = NULL, int Size = 0) = 0; + virtual bool ReceiveOutMessage(Message **Msg) = 0; + virtual bool ReceiveInMessage(Message **Msg) = 0; + + // empty in- and out-message queues + virtual void Purge() = 0; + // empty in-message queue except the message with the ID stored in signal + virtual void PurgeIn(int Signal) = 0; + // empty out-message queue except the message with the ID stored in signal + virtual void PurgeOut(int Signal) = 0; + // get a message from freeMessageQueue or create a new one + virtual Message *GetMessage() = 0; + +protected: + CEvent *containerInEvent; + CEvent *containerOutEvent; // ??? + CCriticalSection criticalSection; // lock object for accessing message queues + + bool inDefered; // Defer messages for in or out + bool outDefered; // Defer messages for in or out +}; diff --git a/adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp b/adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp new file mode 100644 index 0000000..b3b0468 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp @@ -0,0 +1,57 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Communication/Message.hpp" +#include "KodiThreads/threads/CriticalSection.h" + + +class ISocket +{ +public: + ISocket(std::string Name, int ID, size_t Size) : + Name(Name), + ID(ID), + Size(Size) + { + CSingleLock lock(this->Lock); + HasUpdated = false; + } + + virtual ~ISocket() + { + } + + const std::string Name; + const int ID; + const size_t Size; + + CCriticalSection Lock; + bool HasUpdated; + + virtual int Set(Message &Msg) = 0; + virtual void* Get() = 0; +}; + + +// typedef for socket registration +typedef std::vector SocketVector_t; diff --git a/adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp b/adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp new file mode 100644 index 0000000..89d9ead --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp @@ -0,0 +1,70 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp" +#include "adsp.template/Addon/MessageSystem/Communication/Message.hpp" + + +#define CreateTSocketClassMethodCallback(ObjType, Obj, Callback, StringClass, ID) dynamic_cast(new TSocketClassMethodCallback(Obj, Callback, StringClass::ToString(StringClass::ID), StringClass::ID)) + + +template +class TSocketClassMethodCallback : public ISocket +{ +public: + typedef int (T::*SocketCallback)(Message &Msg); + TSocketClassMethodCallback(T *Obj, SocketCallback Callback, std::string Name, int Signal) : ISocket(Name, Signal, sizeof(SocketCallback)) + { + if (!Callback || !Obj) + { + // TODO throw exception + } + + m_Callback = Callback; + m_Obj = Obj; + } + + virtual int Set(Message &Msg) + { + if (Msg.signal != this->ID) + { + // TODO: error code + return -1; + } + + CSingleLock lock(this->Lock); + this->HasUpdated = true; + + return (m_Obj->*m_Callback)(Msg); + } + + virtual void* Get() + { + return &m_Callback; + } + + +protected: + SocketCallback m_Callback; + T *m_Obj; +}; diff --git a/adsp.template/Addon/MessageSystem/Sockets/TSocketForward.hpp b/adsp.template/Addon/MessageSystem/Sockets/TSocketForward.hpp new file mode 100644 index 0000000..78bfe53 --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Sockets/TSocketForward.hpp @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp" +#include "adsp.template/Addon/MessageSystem/Communication/Message.hpp" + + +#define CreateTSocketForward(ObjType, Obj, StringClass, ID) dynamic_cast(new TSocketForward(Obj, StringClass::ToString(StringClass::ID), StringClass::ID)) + + +template +class TSocketForward : public ISocket +{ +public: + TSocketForward(T *Dispatcher, std::string Name, int Signal) : ISocket(Name, Signal, sizeof(TSocketForward)) + { + m_Dispatcher = Dispatcher; + } + + virtual int Set(Message &Msg) + { + if (Msg.signal != this->ID) + { + // TODO: error code + return -1; + } + + CSingleLock lock(this->Lock); + this->HasUpdated = true; + + return m_Dispatcher->SendMsg(nullptr, 0, ISocket::ID); + } + + virtual void* Get() + { + return nullptr; + } + +private: + T *m_Dispatcher; +}; diff --git a/adsp.template/Addon/MessageSystem/Sockets/TSocketMemcpy.hpp b/adsp.template/Addon/MessageSystem/Sockets/TSocketMemcpy.hpp new file mode 100644 index 0000000..737146c --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Sockets/TSocketMemcpy.hpp @@ -0,0 +1,76 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Interfaces/ISocket.hpp" +#include "adsp.template/Addon/MessageSystem/Communication/Message.hpp" + + +#define CreateTSocketMemcpy(Type, ControlledMember, StringClass, ID) dynamic_cast(new TSocketMemcpy(ControlledMember, StringClass::ToString(StringClass::ID), StringClass::ID)) + + +template +class TSocketMemcpy : public ISocket +{ +public: + TSocketMemcpy(T *SocketPtr, std::string Name, int Signal) : ISocket(Name, Signal, sizeof(T)) + { + if (!SocketPtr) + { + // TODO throw exception + } + + m_SocketPtr = SocketPtr; + memcpy(&m_CurrenVal, SocketPtr, this->Size); + } + + + ~TSocketMemcpy() + { + } + + virtual int Set(Message &Msg) + { + if (!Msg.data || Msg.signal != this->ID || Msg.size != this->Size) + { + // TODO: error code + return -1; + } + + CSingleLock lock(this->Lock); + this->HasUpdated = true; + memcpy(&m_CurrenVal, Msg.data, this->Size); + memcpy(this->m_SocketPtr, &m_CurrenVal, this->Size); + + return 0; + } + + virtual void* Get() + { + return &m_CurrenVal; + } + + +protected: + T *m_SocketPtr; + T m_CurrenVal; +}; diff --git a/adsp.template/Addon/MessageSystem/Sockets/TSocketRangeCheck.hpp b/adsp.template/Addon/MessageSystem/Sockets/TSocketRangeCheck.hpp new file mode 100644 index 0000000..3f35a9d --- /dev/null +++ b/adsp.template/Addon/MessageSystem/Sockets/TSocketRangeCheck.hpp @@ -0,0 +1,70 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "adsp.template/Addon/MessageSystem/Sockets/TSocketClassMethodCallback.hpp" + + +#define CreateTSocketRangeCheck(DispatcherClass, RangeType, DispatcherObj, Min, Max, StringClass, ID) dynamic_cast(new TSocketRangeCheck(DispatcherObj, Min, Max, StringClass::ToString(StringClass::ID), StringClass::ID)) + + +template +class TSocketRangeCheck : public TSocketClassMethodCallback> +{ +public: + TSocketRangeCheck(TDispatcher *Dispatcher, T MinValue, T MaxValue, std::string Name, int Signal) : + TSocketClassMethodCallback>(this, &TSocketRangeCheck::RangeCheck, Name, Signal) + { + m_MinValue = MinValue; + m_MaxValue = MaxValue; + m_Dispatcher = Dispatcher; + } + +private: + int RangeCheck(Message &Msg) + { + if (Msg.size != sizeof(T)) + { + // TODO: error code + return -1; + } + + T value = *((T*)Msg.data); + if (!(m_MinValue <= value && value <= m_MaxValue)) + { + // TODO: error code + return -1; + } + + if (!m_Dispatcher->SendMsg(static_cast(&value), sizeof(T), ISocket::ID)) + { + // TODO: error code + return -1; + } + + return 0; + } + + TDispatcher *m_Dispatcher; + T m_MinValue; + T m_MaxValue; +}; diff --git a/adsp.template/Addon/Process/AddonProcessManager.cpp b/adsp.template/Addon/Process/AddonProcessManager.cpp new file mode 100644 index 0000000..ab409d5 --- /dev/null +++ b/adsp.template/Addon/Process/AddonProcessManager.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +#include "AddonProcessManager.hpp" + +#include "include/client.h" + +#include +#include + +using namespace std; +using namespace ADDON; + + +// static member variables +bool CAddonProcessManager::m_IsCreated = false; + + +AE_DSP_ERROR CAddonProcessManager::CreateProcesses() +{ + if (GetProcessMap().size() <= 0) + { + KODI->Log(LOG_NOTICE, "%s, %i, Tried to create CAddonProcessManager without any registered AddonProcesses. Consequently CAddonProcessManager will be disabled.", __FUNCTION__, __LINE__); + + return AE_DSP_ERROR_IGNORE_ME; + } + + AddonProcessVector_t &addonProcesses = GetAddonProcessVector(); + AddonProcessMap_t &processMap = GetProcessMap(); + for (AddonProcessMap_t::iterator iter = processMap.begin(); iter != processMap.end(); ++iter) + { + IAddonProcess* process = iter->second.CreateProcess(); + string processStr = TranslateProcessID_TO_Str(iter->first.ProcessID); + + if (processStr == "") + { + KODI->Log(LOG_NOTICE, "%s, %i, Could not retrieve AddonProcess name! Please contact the author of this add-on with this log file.", __FUNCTION__, __LINE__); + } + + AE_DSP_ERROR err = process->Create(); + if (err != AE_DSP_ERROR_NO_ERROR) + { + delete process; + process = NULL; + KODI->Log(LOG_ERROR, "%s, %i, Failed to create AddonProcess %s with ID: %i!", __FUNCTION__, __LINE__, processStr.c_str(), iter->first.ProcessID); + } + + if (process) + { + KODI->Log(LOG_DEBUG, "%s, %i, Successful created AddonProcess %s with ID: %i", __FUNCTION__, __LINE__, processStr.c_str(), iter->first.ProcessID); + addonProcesses.push_back(process); + } + } + + KODI->Log(LOG_DEBUG, "%s, %i, Successful created %i from %i AddonProcesses, %i failed", __FUNCTION__, __LINE__, addonProcesses.size(), processMap.size(), processMap.size() - addonProcesses.size()); + + m_IsCreated = true; + + return AE_DSP_ERROR_NO_ERROR; +} + + +void CAddonProcessManager::DestroyProcesses() +{ + AddonProcessVector_t &addonProcesses = GetAddonProcessVector(); + for (unsigned int ii = 0; ii < addonProcesses.size(); ii++) + { + if (addonProcesses[ii]) + { + addonProcesses[ii]->DisconnectAll(); + AE_DSP_ERROR err = addonProcesses[ii]->Destroy(); + if (err != AE_DSP_ERROR_NO_ERROR) + { + KODI->Log(LOG_ERROR, "%s, %i, An error occured during AddonProcess destruction! Please contact the author of this add-on with this log file.", __FUNCTION__, __LINE__); + } + + delete addonProcesses[ii]; + } + + addonProcesses[ii] = NULL; + } + + addonProcesses.clear(); + m_IsCreated = false; +} + + +int CAddonProcessManager::RegisterAddonProcess(const std::string ProcessName, AddonProcessCallbacks_t Callbacks) +{ + if (m_IsCreated) + { + KODI->Log(LOG_ERROR, "%s, %i, It is not possible to add new AddonProcesses, when the CAddonProcessManager is already created!", __FUNCTION__, __LINE__); + + return -1; + } + + static int processID=0; + AddonProcessKey_t processKey(processID); + AddonProcessMap_t::iterator iter = GetProcessMap().find(processKey); + if (iter == GetProcessMap().end()) + {// only register not yet known products + GetProcessMap()[processKey] = Callbacks; + } + + GetAddonProcessNameMap()[ProcessName] = processKey; + + return processID++; +} + + +int CAddonProcessManager::GetActiveProcesses(std::string &ProcessName) +{ + AddonProcessNameMap_t &addonProcessNameMappingTable = GetAddonProcessNameMap(); + AddonProcessNameMap_t::iterator iterModeKey = addonProcessNameMappingTable.find(ProcessName); + if (iterModeKey == addonProcessNameMappingTable.end()) + { + return -1; + } + + AddonProcessMap_t::iterator iterCB = GetProcessMap().find((*iterModeKey).second); + if (iterCB == GetProcessMap().end()) + { + return -1; + } + + return (*iterCB).second.GetActiveProcesses(); +} + + +int CAddonProcessManager::GetCreatedProcesses(std::string &ProcessName) +{ + AddonProcessNameMap_t &addonProcessNameMappingTable = GetAddonProcessNameMap(); + AddonProcessNameMap_t::iterator iterModeKey = addonProcessNameMappingTable.find(ProcessName); + if (iterModeKey == addonProcessNameMappingTable.end()) + { + return -1; + } + + AddonProcessMap_t::iterator iterCB = GetProcessMap().find((*iterModeKey).second); + if (iterCB == GetProcessMap().end()) + { + return -1; + } + + return (*iterCB).second.GetCreatedProcesses(); +} + +int CAddonProcessManager::GetDestroyedProcesses(std::string &ProcessName) +{ + AddonProcessNameMap_t &addonProcessNameMappingTable = GetAddonProcessNameMap(); + AddonProcessNameMap_t::iterator iterModeKey = addonProcessNameMappingTable.find(ProcessName); + if (iterModeKey == addonProcessNameMappingTable.end()) + { + return -1; + } + + AddonProcessMap_t::iterator iterCB = GetProcessMap().find((*iterModeKey).second); + if (iterCB == GetProcessMap().end()) + { + return -1; + } + + return (*iterCB).second.GetDestroyedProcesses(); +} + +int CAddonProcessManager::ConnectObject(MVCObject *Object) +{ + AddonProcessVector_t &addonProcesses = GetAddonProcessVector(); + for (AddonProcessVector_t::iterator iter = addonProcesses.begin(); iter != addonProcesses.end(); ++iter) + { + (*iter)->ConnectObject(Object); + } + + return 0; // TODO return value +} + +int CAddonProcessManager::DisconnectObject(MVCObject *Object) +{ + AddonProcessVector_t &addonProcesses = GetAddonProcessVector(); + for (AddonProcessVector_t::iterator iter = addonProcesses.begin(); iter != addonProcesses.end(); ++iter) + { + (*iter)->DisconnectObject(Object); + } + + return 0; +} diff --git a/adsp.template/Addon/Process/AddonProcessManager.hpp b/adsp.template/Addon/Process/AddonProcessManager.hpp new file mode 100644 index 0000000..ea6f967 --- /dev/null +++ b/adsp.template/Addon/Process/AddonProcessManager.hpp @@ -0,0 +1,192 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "IAddonProcess.hpp" +#include "adsp.template/Addon/Utils/TCreationStatistics.hpp" +#include "adsp.template/Addon/MVC/Interfaces/MVCObject.hpp" +#include + +#include +#include + +// Type: +// AE_DSP_MODE_TYPE_INPUT_RESAMPLE = 0, /*!< @brief for input re sample */ +// AE_DSP_MODE_TYPE_PRE_PROCESS = 1, /*!< @brief for preprocessing */ +// AE_DSP_MODE_TYPE_MASTER_PROCESS = 2, /*!< @brief for master processing */ +// AE_DSP_MODE_TYPE_POST_PROCESS = 3, /*!< @brief for post processing */ +// AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE = 4, /*!< @brief for output re sample */ +#define REGISTER_ADDON_PROCESS_CLASS(AddonProcess, ProcessName) public IAddonProcess, \ + public CAddonProcessManager::TRegisterAddonProcess + + +class CAddonProcessManager +{ +public: + typedef struct AddonProcessKey_t + { + int ProcessID; + + AddonProcessKey_t() + { + ProcessID = -1; + } + + AddonProcessKey_t(int ID) + { + ProcessID = ID; + } + }AddonProcessKey_t; + + typedef struct + { + std::string ProcessName; + AddonProcessKey_t ProcessInfo; + }AddonProcessInfo_t; + + typedef std::vector AddonProcessInfoVector_t; + +private: + typedef std::vector AddonProcessVector_t; + typedef IAddonProcess* (*AddonProcessCreateCallback)(); + typedef const AE_DSP_MODES::AE_DSP_MODE& (*ADSPModeSettingsCallback)(); + typedef int(*ADSPModeStatisticCallback)(); + typedef struct AddonProcessCallbacks_t + { + AddonProcessCreateCallback CreateProcess; + ADSPModeStatisticCallback GetActiveProcesses; + ADSPModeStatisticCallback GetCreatedProcesses; + ADSPModeStatisticCallback GetDestroyedProcesses; + }AddonProcessCallbacks_t; + + class CPAddonProcessKeyCmp + { + public: + bool operator()(const AddonProcessKey_t &Obj1, const AddonProcessKey_t &Obj2) const + { + return Obj1.ProcessID < Obj2.ProcessID; + } + }; + + typedef std::map AddonProcessMap_t; + typedef std::map AddonProcessNameMap_t; + +public: + template + class TRegisterAddonProcess : public TCreationStatistics + { + friend class CAddonProcessManager; + + public: + TRegisterAddonProcess() : m_HiddenID(ProcessID) {} // force registration by assinging ProcessID to m_HiddenID + + static const int ProcessID; + static const char* ProcessName; + + static IAddonProcess* Create() { return dynamic_cast(new TAddonProcess); } + static const AE_DSP_MODES::AE_DSP_MODE& GetADSPModeSettings() { return m_ModeSettings; } + + private: + const int m_HiddenID; // force initialization for m_HiddenID + static AddonProcessCallbacks_t m_Callbacks; + static const AE_DSP_MODES::AE_DSP_MODE m_ModeSettings; + }; + + static AE_DSP_ERROR CreateProcesses(); + static void DestroyProcesses(); + + static int RegisterAddonProcess(const std::string ProcessName, AddonProcessCallbacks_t Callbacks); + + static int GetActiveProcesses(std::string &ProcessName); + static int GetCreatedProcesses(std::string &ProcessName); + static int GetDestroyedProcesses(std::string &ProcessName); + + static int ConnectObject(MVCObject *Object); + static int DisconnectObject(MVCObject *Object); + +private: + // Force initialization and creation of product map by using a static method and a std::map + inline static AddonProcessMap_t& GetProcessMap() + { + static AddonProcessMap_t s_AddonProcesses; + + return s_AddonProcesses; + } + + static bool ProcessIDSort(AddonProcessInfo_t &Process1, AddonProcessInfo_t &Process2) + { + return (Process1.ProcessInfo.ProcessID < Process2.ProcessInfo.ProcessID); + } + + static std::string TranslateProcessID_TO_Str(int ProcessID) + { + std::string processStr = ""; + + for (AddonProcessNameMap_t::iterator iter = GetAddonProcessNameMap().begin(); iter != GetAddonProcessNameMap().end(); ++iter) + { + if (ProcessID == iter->second.ProcessID) + { + processStr = iter->first; + break; + } + } + + return processStr; + } + + inline static AddonProcessNameMap_t& GetAddonProcessNameMap() + { + static AddonProcessNameMap_t s_ProcessNameMappingTable; + + return s_ProcessNameMappingTable; + } + + inline static AddonProcessVector_t& GetAddonProcessVector() + { + static AddonProcessVector_t s_AddonProcesses; + + return s_AddonProcesses; + } + + static bool m_IsCreated; +}; + + +template +const int CAddonProcessManager::TRegisterAddonProcess::ProcessID = +CAddonProcessManager::RegisterAddonProcess(TProcessName::ProcessName, CAddonProcessManager::TRegisterAddonProcess::m_Callbacks); + +template +const char* CAddonProcessManager::TRegisterAddonProcess::ProcessName = TProcessName::ProcessName; + +template +const AE_DSP_MODES::AE_DSP_MODE CAddonProcessManager::TRegisterAddonProcess::m_ModeSettings; + +template +CAddonProcessManager::AddonProcessCallbacks_t +CAddonProcessManager::TRegisterAddonProcess::m_Callbacks = +{ + CAddonProcessManager::TRegisterAddonProcess::Create, + CAddonProcessManager::TRegisterAddonProcess::GetStatisticsActive, + CAddonProcessManager::TRegisterAddonProcess::GetStatisticsCreated, + CAddonProcessManager::TRegisterAddonProcess::GetStatisticsDestroyed +}; diff --git a/adsp.template/Addon/Process/IAddonProcess.hpp b/adsp.template/Addon/Process/IAddonProcess.hpp new file mode 100644 index 0000000..897ea5c --- /dev/null +++ b/adsp.template/Addon/Process/IAddonProcess.hpp @@ -0,0 +1,215 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +#include "kodi/kodi_adsp_types.h" + +#include "adsp.template/Addon/MVC/Interfaces/MVCObject.hpp" + +#include + +class CAddonProcessManager; + + +class IAddonProcess +{ + friend class CAddonProcessManager; + typedef std::list MVCObjectList_t; +public: + IAddonProcess(int ConnectionID) : + ConnectionID(ConnectionID) + { + m_Controller = nullptr; + m_Model = nullptr; + m_Views.clear(); + } + + virtual ~IAddonProcess() + { + } + + const int ConnectionID; + +// Fixed public methods + virtual AE_DSP_ERROR Create() = 0; + virtual AE_DSP_ERROR Destroy() = 0; + + virtual bool ConnectObject(MVCObject *Object) + { + if (Object->ConnectionID != this->ConnectionID) + { + return false; + } + + switch (Object->Type) + { + case MVCObject::MODEL_OBJECT: + if (m_Model && m_Controller) + {// disconnect this model + m_Model->DisconnectDispatcher(m_Controller); + m_Controller->DisconnectDispatcher(m_Model); + m_Model = nullptr; + } + + m_Model = Object; + break; + + case MVCObject::VIEW_OBJECT: + {// register view only once + bool found = false; + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + { + if (*iter == Object) + { + found = true; + break; + } + } + + if (!found) + { + m_Views.push_back(Object); + } + } + break; + + case MVCObject::CONTROLLER_OBJECT: + if (m_Controller) + { + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + {// disconnect all views + (*iter)->DisconnectDispatcher(m_Controller); + } + + if (m_Model) + {// disconnect model + m_Model->DisconnectDispatcher(m_Controller); + } + } + + m_Controller = Object; + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + {// connect all registered views + (*iter)->ConnectDispatcher(m_Controller); + } + + if (m_Model) + {// connect registered model + m_Model->ConnectDispatcher(m_Controller); + } + break; + + default: + return false; + } + + if (Object->Type != MVCObject::CONTROLLER_OBJECT && m_Controller) + { + Object->ConnectDispatcher(m_Controller); + m_Controller->ConnectDispatcher(Object); + } + + return true; + } + + virtual bool DisconnectObject(MVCObject *Object) + { + if (Object->ConnectionID != this->ConnectionID) + { + return false; + } + + switch (Object->Type) + { + case MVCObject::MODEL_OBJECT: + if (m_Model == Object && m_Controller) + { + m_Controller->DisconnectDispatcher(m_Model); + m_Model->DisconnectDispatcher(m_Controller); + } + m_Model = nullptr; + break; + + case MVCObject::VIEW_OBJECT: + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + { + if (*iter == Object) + { + if (m_Controller) + { + m_Controller->DisconnectDispatcher(*iter); + (*iter)->DisconnectDispatcher(m_Controller); + } + + m_Views.erase(iter); + break; + } + } + break; + + case MVCObject::CONTROLLER_OBJECT: + if (m_Controller == Object) + { + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + { + (*iter)->DisconnectDispatcher(m_Controller); + m_Controller->DisconnectDispatcher(*iter); + } + + if (m_Model) + { + m_Model->DisconnectDispatcher(m_Controller); + m_Controller->DisconnectDispatcher(m_Model); + } + + m_Controller = nullptr; + } + break; + + default: + return false; + } + + return true; + } + + void DisconnectAll() + { + if (m_Controller) + { + for (MVCObjectList_t::iterator iter = m_Views.begin(); iter != m_Views.end(); ++iter) + { + (*iter)->DisconnectDispatcher(m_Controller); + } + + if (m_Model) + { + m_Model->DisconnectDispatcher(m_Controller); + } + } + m_Views.clear(); + } + +private: + MVCObject *m_Controller; + MVCObject *m_Model; + MVCObjectList_t m_Views; +}; diff --git a/adsp.template/Addon/Utils/EnumIDsToString.hpp b/adsp.template/Addon/Utils/EnumIDsToString.hpp new file mode 100644 index 0000000..798753c --- /dev/null +++ b/adsp.template/Addon/Utils/EnumIDsToString.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2005-2016 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 3, 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 + * . + * + */ + + + +#undef BEGIN_ENUM_ID_CLASS +#undef ADD_ENUM_ID +#undef END_ENUM_ID_CLASS + + +#if !defined(CREATE_ENUM_ID_STRINGS) +#define BEGIN_ENUM_ID_CLASS(ID) class C##ID { public: typedef enum { INVALID_ENUM_ID = -1, +#define ADD_ENUM_ID(ID) ID, +#define END_ENUM_ID_CLASS(ID) MAX_ENUM_ID } e##ID; static const char* ToString(e##ID EnumId); private: static const char *m_EnumStrs[MAX_ENUM_ID]; }; +#else +#define BEGIN_ENUM_ID_CLASS(ID) const char *C##ID::m_EnumStrs[C##ID::MAX_ENUM_ID] = { +#define ADD_ENUM_ID(ID) #ID, +#define END_ENUM_ID_CLASS(ID) }; \ + const char* C##ID::ToString(C##ID::e##ID EnumId) { \ + if(EnumId <= C##ID::INVALID_ENUM_ID) return "INVALID_ENUM_ID"; \ + if(EnumId >= C##ID::MAX_ENUM_ID) return "MAX_ENUM_ID"; \ + return m_EnumStrs[EnumId]; \ + } +#endif diff --git a/adsp.template/Addon/Utils/TCreationStatistics.hpp b/adsp.template/Addon/Utils/TCreationStatistics.hpp new file mode 100644 index 0000000..1f76db1 --- /dev/null +++ b/adsp.template/Addon/Utils/TCreationStatistics.hpp @@ -0,0 +1,68 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +template +class TCreationStatistics +{ +public: + TCreationStatistics() + { + m_Created++; + m_Active++; + } + + ~TCreationStatistics() + { + m_Destroyed++; + m_Active--; + } + + static int GetStatisticsCreated() + { + return m_Created; + } + + static int GetStatisticsActive() + { + return m_Active; + } + + static int GetStatisticsDestroyed() + { + return m_Destroyed; + } + + +private: + static int m_Created; + static int m_Active; + static int m_Destroyed; +}; + +template +int TCreationStatistics::m_Created; + +template +int TCreationStatistics::m_Active; + +template +int TCreationStatistics::m_Destroyed; diff --git a/adsp.template/AddonExceptions/IAddonException.h b/adsp.template/AddonExceptions/IAddonException.h new file mode 100644 index 0000000..3fa4bb4 --- /dev/null +++ b/adsp.template/AddonExceptions/IAddonException.h @@ -0,0 +1,49 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include + +template +class IAddonException +{ + public: + IAddonException(std::string Function="", std::string Filename="", int Line=-1, std::string Module="") + { + m_Function = Function; + m_Filename = Filename; + m_Line = Line; + m_Module = Module; + m_Line = Line; + } + + virtual ~IAddonException() {} + + virtual T &what() = 0; + + protected: + T m_Exception; + std::string m_Function; + std::string m_Filename; + std::string m_Module; + int m_Line; +}; diff --git a/adsp.template/AddonExceptions/TAddonException.h b/adsp.template/AddonExceptions/TAddonException.h new file mode 100644 index 0000000..4bef9f7 --- /dev/null +++ b/adsp.template/AddonExceptions/TAddonException.h @@ -0,0 +1,52 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include "IAddonException.h" + +template +class TAddonException : public IAddonException +{ + public: + TAddonException(T Exception, std::string Function="", std::string Filename="", int Line=-1, std::string Module="") + : IAddonException(Function, Filename, Line, Module) + { + IAddonException::m_Exception = Exception; + } + + virtual ~TAddonException() {} + + virtual T &what() { return IAddonException::m_Exception; } +}; + +// type definitions +typedef TAddonException CAddonStringException; + +#if defined (TARGET_WINDOWS) + #ifndef __func__ + #define __func__ __FUNCTION__ + #endif +#endif + +#define ADDON_STRING_EXCEPTION_HANDLER(ErrorStr) CAddonStringException(ErrorStr, __func__, __FILE__, __LINE__) +#define ADDON_STRING_MODULE_EXCEPTION_HANDLER(ErrorStr, Module) CAddonStringException(ErrorStr, __func__, __FILE__, __LINE__, Module) diff --git a/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.cpp b/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.cpp new file mode 100644 index 0000000..523cf6f --- /dev/null +++ b/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +#include "FactoryADSPModes.hpp" + +#include +#include + +using namespace std; + + +AE_DSP_ERROR CFactoryADSPModes::Create(int ModeID, AE_DSP_MODE_TYPE ModeType, IADSPMode *&InterfacePtr) +{ + ADSPModeKey_t ADSPModeKey(ModeID, ModeType); + ADSPModeMap_t::iterator iter = GetADSPModeMap().find(ADSPModeKey); + if (iter == GetADSPModeMap().end()) + { + InterfacePtr = NULL; + return AE_DSP_ERROR_INVALID_PARAMETERS; + } + + InterfacePtr = (*iter).second.CreateADSPMode(); + InterfacePtr->m_ModeID = ModeID; + InterfacePtr->m_ModeType = ModeType; + return AE_DSP_ERROR_NO_ERROR; +} + + +void CFactoryADSPModes::Destroy(IADSPMode *&ADSPMode) +{ + if (ADSPMode) + { + delete ADSPMode; + ADSPMode = NULL; + } +} + + +int CFactoryADSPModes::RegisterADSPMode(const std::string ModeName, AE_DSP_MODE_TYPE ModeType, ADSPModeCallbacks_t Callbacks) +{ + static int modeID=0; + ADSPModeKey_t ADSPModeKey(modeID, ModeType); + ADSPModeMap_t::iterator iter = GetADSPModeMap().find(ADSPModeKey); + if (iter == GetADSPModeMap().end()) + {// only register not yet known products + GetADSPModeMap()[ADSPModeKey] = Callbacks; + + const AE_DSP_MODES::AE_DSP_MODE& modeSettings = Callbacks.GetADSPModeSettings(); + ((AE_DSP_MODES::AE_DSP_MODE*)&modeSettings)->iUniqueDBModeId = -1; + ((AE_DSP_MODES::AE_DSP_MODE*)&modeSettings)->iModeType = ModeType; + ((AE_DSP_MODES::AE_DSP_MODE*)&modeSettings)->iModeNumber = modeID; + } + + GetADSPModeNameMap()[ModeName] = ADSPModeKey; + + return modeID++; +} + + +AE_DSP_ERROR CFactoryADSPModes::GetAvailableModes(ADSPModeInfoVector_t &ModeInfos) +{ + ModeInfos.clear(); + + ADSPModeNameMap_t &modeNameMap = GetADSPModeNameMap(); + if (modeNameMap.size() <= 0) + { + return AE_DSP_ERROR_FAILED; + } + + for (ADSPModeNameMap_t::iterator iter = modeNameMap.begin(); iter != modeNameMap.end(); ++iter) + { + ADSPModeInfo_t modeInfo; + modeInfo.ModeName = iter->first; + modeInfo.ModeInfo.ModeID = iter->second.ModeID; + modeInfo.ModeInfo.ModeType = iter->second.ModeType; + + ModeInfos.push_back(modeInfo); + } + + // Later modules will need a consecutive mode id order + sort(ModeInfos.begin(), ModeInfos.end(), ModeIDSort); + + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CFactoryADSPModes::GetADSPModeSettings(int ModeID, AE_DSP_MODE_TYPE ModeType, AE_DSP_MODES::AE_DSP_MODE &ModeSettings) +{ + ADSPModeKey_t ADSPModeKey(ModeID, ModeType); + ADSPModeMap_t::iterator iter = GetADSPModeMap().find(ADSPModeKey); + if (iter == GetADSPModeMap().end()) + { + return AE_DSP_ERROR_INVALID_PARAMETERS; + } + + const AE_DSP_MODES::AE_DSP_MODE& modeSettings = (*iter).second.GetADSPModeSettings(); + memcpy(&ModeSettings, &modeSettings, sizeof(AE_DSP_MODES::AE_DSP_MODE)); + + return AE_DSP_ERROR_NO_ERROR; +} + + +int CFactoryADSPModes::GetActiveADSPMode(std::string &ModeName) +{ + ADSPModeNameMap_t &modeNameMap = GetADSPModeNameMap(); + ADSPModeNameMap_t::iterator iterModeKey = modeNameMap.find(ModeName); + if (iterModeKey == modeNameMap.end()) + { + return -1; + } + + ADSPModeMap_t::iterator iterCB = GetADSPModeMap().find((*iterModeKey).second); + if (iterCB == GetADSPModeMap().end()) + { + return -1; + } + + return (*iterCB).second.GetActiveADSPMode(); +} + + +int CFactoryADSPModes::GetCreatedADSPMode(std::string &ModeName) +{ + ADSPModeNameMap_t &modeNameMap = GetADSPModeNameMap(); + ADSPModeNameMap_t::iterator iterModeKey = modeNameMap.find(ModeName); + if (iterModeKey == modeNameMap.end()) + { + return -1; + } + + ADSPModeMap_t::iterator iterCB = GetADSPModeMap().find((*iterModeKey).second); + if (iterCB == GetADSPModeMap().end()) + { + return -1; + } + + return (*iterCB).second.GetCreatedADSPMode(); +} + +int CFactoryADSPModes::GetDestroyedADSPMode(std::string &ModeName) +{ + ADSPModeNameMap_t &modeNameMap = GetADSPModeNameMap(); + ADSPModeNameMap_t::iterator iterModeKey = modeNameMap.find(ModeName); + if (iterModeKey == modeNameMap.end()) + { + return -1; + } + + ADSPModeMap_t::iterator iterCB = GetADSPModeMap().find((*iterModeKey).second); + if (iterCB == GetADSPModeMap().end()) + { + return -1; + } + + return (*iterCB).second.GetDestroyedADSPMode(); +} diff --git a/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp b/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp new file mode 100644 index 0000000..8bd2501 --- /dev/null +++ b/adsp.template/AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp @@ -0,0 +1,172 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "IADSPMode.hpp" +#include "adsp.template/Addon/Utils/TCreationStatistics.hpp" +#include + +#include +#include + +// Type: +// AE_DSP_MODE_TYPE_INPUT_RESAMPLE = 0, /*!< @brief for input re sample */ +// AE_DSP_MODE_TYPE_PRE_PROCESS = 1, /*!< @brief for preprocessing */ +// AE_DSP_MODE_TYPE_MASTER_PROCESS = 2, /*!< @brief for master processing */ +// AE_DSP_MODE_TYPE_POST_PROCESS = 3, /*!< @brief for post processing */ +// AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE = 4, /*!< @brief for output re sample */ +#define REGISTER_ADSP_MODE_CLASS(ADSPMode, ModeName, ModeSettings, Type) public IADSPMode, \ + public CFactoryADSPModes::TRegisterADSPMode + + +class CFactoryADSPModes +{ +public: + typedef struct ADSPModeKey_t + { + int ModeID; + AE_DSP_MODE_TYPE ModeType; + + ADSPModeKey_t() + { + ModeID = -1; + ModeType = AE_DSP_MODE_TYPE_UNDEFINED; + } + + ADSPModeKey_t(int ID, AE_DSP_MODE_TYPE Type) + { + ModeID = ID; + ModeType = Type; + } + }ADSPModeKey_t; + + typedef struct + { + std::string ModeName; + ADSPModeKey_t ModeInfo; + }ADSPModeInfo_t; + + typedef std::vector ADSPModeInfoVector_t; + +private: + typedef IADSPMode* (*ADSPModeCreateCallback)(); + typedef const AE_DSP_MODES::AE_DSP_MODE& (*ADSPModeSettingsCallback)(); + typedef int(*ADSPModeStatisticCallback)(); + typedef struct ADSPModeCallbacks_t + { + ADSPModeCreateCallback CreateADSPMode; + ADSPModeStatisticCallback GetActiveADSPMode; + ADSPModeStatisticCallback GetCreatedADSPMode; + ADSPModeStatisticCallback GetDestroyedADSPMode; + ADSPModeSettingsCallback GetADSPModeSettings; + }ADSPModeCallbacks_t; + + class CADSPModeKeyCmp + { + public: + bool operator()(const ADSPModeKey_t &Obj1, const ADSPModeKey_t &Obj2) const + { + return Obj1.ModeID < Obj2.ModeID || (Obj1.ModeID == Obj2.ModeID && Obj1.ModeType < Obj2.ModeType); + } + }; + + typedef std::map ADSPModeMap_t; + typedef std::map ADSPModeNameMap_t; + +public: + template + class TRegisterADSPMode : public TCreationStatistics + { + friend class CFactoryADSPModes; + + public: + TRegisterADSPMode() : m_HiddenID(ModeID) {} // force registration by assinging ModeID to m_HiddenID + + static const int ModeID; + static const AE_DSP_MODE_TYPE ModeType; + static const char* ModeName; + + static IADSPMode* Create() { return dynamic_cast(new TADSPMode); } + static const AE_DSP_MODES::AE_DSP_MODE& GetADSPModeSettings() { return m_ModeSettings; } + + private: + const int m_HiddenID; // force initialization for m_HiddenID + static const TModeSettings m_ModeSettings; + static ADSPModeCallbacks_t m_Callbacks; + }; + + static AE_DSP_ERROR Create(int ModeID, AE_DSP_MODE_TYPE ModeType, IADSPMode *&InterfacePtr); + static void Destroy(IADSPMode *&ADSPMode); + static int RegisterADSPMode(const std::string ModeName, AE_DSP_MODE_TYPE ModeType, ADSPModeCallbacks_t Callbacks); + static AE_DSP_ERROR GetAvailableModes(ADSPModeInfoVector_t &ModeInfos); + static AE_DSP_ERROR GetADSPModeSettings(int ModeID, AE_DSP_MODE_TYPE ModeType, AE_DSP_MODES::AE_DSP_MODE &adspModeSettings); + + static int GetActiveADSPMode(std::string &ModeName); + static int GetCreatedADSPMode(std::string &ModeName); + static int GetDestroyedADSPMode(std::string &ModeName); + +private: + // Force initialization and creation of product map by using a static method and a std::map + inline static ADSPModeMap_t& GetADSPModeMap() + { + static ADSPModeMap_t s_ADSPModes; + + return s_ADSPModes; + } + + static bool ModeIDSort(ADSPModeInfo_t &Mode1, ADSPModeInfo_t &Mode2) + { + return (Mode1.ModeInfo.ModeID < Mode2.ModeInfo.ModeID); + } + + inline static ADSPModeNameMap_t& GetADSPModeNameMap() + { + static ADSPModeNameMap_t s_ModeNameMappingTable; + + return s_ModeNameMappingTable; + } +}; + + +template +const int CFactoryADSPModes::TRegisterADSPMode::ModeID = +CFactoryADSPModes::RegisterADSPMode(TModeName::ModeName, TType, CFactoryADSPModes::TRegisterADSPMode::m_Callbacks); + +template +const AE_DSP_MODE_TYPE CFactoryADSPModes::TRegisterADSPMode::ModeType = TType; + +template +const char* CFactoryADSPModes::TRegisterADSPMode::ModeName = TModeName::ModeName; + +template +const TModeSettings CFactoryADSPModes::TRegisterADSPMode::m_ModeSettings; + +template +CFactoryADSPModes::ADSPModeCallbacks_t +CFactoryADSPModes::TRegisterADSPMode::m_Callbacks = +{ + CFactoryADSPModes::TRegisterADSPMode::Create, + CFactoryADSPModes::TRegisterADSPMode::GetStatisticsActive, + CFactoryADSPModes::TRegisterADSPMode::GetStatisticsCreated, + CFactoryADSPModes::TRegisterADSPMode::GetStatisticsDestroyed, + CFactoryADSPModes::TRegisterADSPMode::GetADSPModeSettings +}; diff --git a/adsp.template/AudioDSP/FactoryADSPModes/IADSPMode.hpp b/adsp.template/AudioDSP/FactoryADSPModes/IADSPMode.hpp new file mode 100644 index 0000000..7cd7ce1 --- /dev/null +++ b/adsp.template/AudioDSP/FactoryADSPModes/IADSPMode.hpp @@ -0,0 +1,192 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + +#include "kodi/kodi_adsp_types.h" + +#include "adsp.template/ADSPHelpers.h" + +#include + +class CFactoryADSPModes; + + +class IADSPMode +{ + friend class CFactoryADSPModes; + +public: + IADSPMode() + { + ResetStreamSettings(); + } + + virtual ~IADSPMode() + { + ResetStreamSettings(); + } + + +// Fixed public methods + AE_DSP_ERROR Create(const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties) + { + memcpy((void*)&m_StreamSettings, Settings, sizeof(AE_DSP_SETTINGS)); + memcpy((void*)&m_StreamProperties, pProperties, sizeof(AE_DSP_STREAM_PROPERTIES)); + + return ModeCreate(m_StreamSettings, m_StreamProperties); + } + + AE_DSP_ERROR Initialize(const AE_DSP_SETTINGS *Settings) + { + if (!CADSPHelpers::CmpStreamSettings(*Settings, m_StreamSettings)) + { + return AE_DSP_ERROR_NO_ERROR; + } + + // If stream settings have changed then copy them and recreate AudioDSP processing mode + memcpy((void*)&m_StreamSettings, Settings, sizeof(AE_DSP_SETTINGS)); + + return ModeCreate(m_StreamSettings, m_StreamProperties); + } + + //! This gets the current stream settings and properties. + /*! + * Get stream settings and properties. For details see and AE_DSP_STREAM_PROPERTIES structures. + * If the add-on operate with buffered arrays and the output size can be higher as + * the input it becomes asked about needed size before any PostProcess call. + * @param pSettings Stream settings for details see AE_DSP_SETTINGS. + * @param pProperties Stream properties for details see AE_DSP_STREAM_PROPERTIES. + * @return AE_DSP_ERROR_INVALID_PARAMETERS: if your input parameters were invalid. + * AE_DSP_ERROR_NO_ERROR: if all was ok. + */ + AE_DSP_ERROR GetStreamInfos(const AE_DSP_SETTINGS& Settings, const AE_DSP_STREAM_PROPERTIES& Properties, void *CustomStreamInfos = NULL) + { + memcpy((void*)&Settings, &m_StreamSettings, sizeof(AE_DSP_SETTINGS)); + memcpy((void*)&Properties, &m_StreamProperties, sizeof(AE_DSP_STREAM_PROPERTIES)); + + //if (CustomStreamInfos) + //{ + // return GetCustomStreamInfos(CustomStreamInfos); + //} + + return AE_DSP_ERROR_NO_ERROR; + } + + +// Requiered Create/Destroy Methods + virtual AE_DSP_ERROR ModeCreate(const AE_DSP_SETTINGS &Settings, const AE_DSP_STREAM_PROPERTIES &Properties) = 0; + virtual void ModeDestroy() = 0; + +// Requiered Processing Methods + virtual unsigned int ModeProcess(float **Array_in, float **Array_out, unsigned int Samples) = 0; + + +// Optional common Methods + virtual unsigned int NeededSamplesize() + { + return 0; + } + + virtual float GetDelay() + { + return (float)m_StreamSettings.iInFrames / (float)m_StreamSettings.iInSamplerate; + } + + //! This method checks the input stream and can filter processing mode types. + /*! + * Ask the add-on about a requested processing mode that it is supported on the current + * stream. Is called about every add-on mode after successed StreamCreate. + * @param Type The processing mode type, see AE_DSP_MODE_TYPE for definitions + * @param ModeID The mode inside add-on which must be performed on call. + * Id is set from add-on and can be modified templateConfiguration.cpp by + * editing adspPreModeNum array. Best practise is to use a global enum to + * have only a mode id once. For example see adspProcessingModeIDs in + * templateConfiguration.h + * @param UniqueDBModeID The Mode unique id generated from dsp database. + * @return AE_DSP_ERROR_NO_ERROR if the properties were fetched successfully. + * If the stream is not supported the ADSP addon must return AE_DSP_ERROR_IGNORE_ME. + * @remarks By default this method accept all processing types. + * If you wanna filter processing mode types then you have to overload this method in + * your processing class. + */ + virtual AE_DSP_ERROR StreamIsModeSupported(AE_DSP_MODE_TYPE Type, unsigned int ModeID, int UniqueDBModeID) + { + UniqueDBModeID; // prevent compiler warnings, because adsp.template doesn't use this information + + if (Type != m_ModeType || ModeID != m_ModeID) + { + return AE_DSP_ERROR_IGNORE_ME; + } + + return AE_DSP_ERROR_NO_ERROR; + } + + +// Optional Methods for Master Modes + virtual int MasterProcessGetOutChannels(unsigned long &OutChannelFlags) + { + return -1; + } + + //! Returns an information string, which will be shown in the UI. + /*! + * @return A string to show. This method always returns a empty string. + * @remarks If you wanna return a custom string, then you must overload this method + * in your processing class. + */ + virtual const char *MasterProcessGetStreamInfoString() + { + return ""; + } + + +// Optional Resampling Methods + virtual int ResamplingRate() + { + return m_StreamSettings.iProcessSamplerate; + } + +protected: + unsigned int m_ModeID; + AE_DSP_MODE_TYPE m_ModeType; + ////! ToDo: description. + ///*! + //* Returns ToDo! + //* @return ToDo! + //* @remarks ToDo! + //*/ + //virtual AE_DSP_ERROR GetCustomStreamInfos(void *CustomStreamSettings) + //{ + // return AE_DSP_ERROR_NO_ERROR; + //} + +private: + void ResetStreamSettings() + { + memset(&m_StreamSettings, 0, sizeof(AE_DSP_SETTINGS)); + memset(&m_StreamProperties, 0, sizeof(AE_DSP_STREAM_PROPERTIES)); + } + + //! Used stream settings for details see AE_DSP_SETTINGS. + AE_DSP_SETTINGS m_StreamSettings; + //! Used stream properties for details see AE_DSP_STREAM_PROPERTIES. + AE_DSP_STREAM_PROPERTIES m_StreamProperties; +}; diff --git a/adsp.template/AudioDSP/Streams/ADSPStream.cpp b/adsp.template/AudioDSP/Streams/ADSPStream.cpp new file mode 100644 index 0000000..54a49a9 --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStream.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "ADSPStream.hpp" +#include "AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp" + +#include "Addon/MVC/Interfaces/MVCObject.hpp" + +#include "Addon/Process/AddonProcessManager.hpp" + +#include "include/client.h" + +using namespace ADDON; + + +CADSPStream::CADSPStream() +{ + m_MaxADSPModes = 0; + m_ADSPModes = NULL; + + m_CurrentMasterMode = NULL; + m_CurrentInputResampleMode = NULL; + m_CurrentOutputResampleMode = NULL; +} + + +CADSPStream::~CADSPStream() +{ +} + + +AE_DSP_ERROR CADSPStream::Create(const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties) +{ + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStream::Destroy() +{ + for (ADSPModeVector_t::iterator iter = m_ADSPModeVector.begin(); iter != m_ADSPModeVector.end(); ++iter) + { + IADSPMode *mode = *iter; + if (mode) + { + MVCObject *object = dynamic_cast(*iter); + if (object) + { // when this mode can be casted to CMessageDispatcher + // notify all created addon processes to disconnect this object + CAddonProcessManager::DisconnectObject(object); + } + + mode->ModeDestroy(); + CFactoryADSPModes::Destroy(mode); + *iter = NULL; + } + } + + m_ADSPModeVector.clear(); + m_MaxADSPModes = 0; + m_ADSPModes = NULL; + m_CurrentMasterMode = NULL; + m_CurrentInputResampleMode = NULL; + m_CurrentOutputResampleMode = NULL; + + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStream::StreamIsModeSupported(AE_DSP_MODE_TYPE ModeType, unsigned int ModeID, int UniqueDBModeID) +{ + if (ModeID >= m_MaxADSPModes) + { + AE_DSP_ERROR_FAILED; + } + + return m_ADSPModes[ModeID]->StreamIsModeSupported(ModeType, ModeID, UniqueDBModeID); +} + + +unsigned int CADSPStream::ProcessMode(unsigned int ModeID, float **ArrayIn, float **ArrayOut, unsigned int Samples) +{ + if (ModeID >= m_MaxADSPModes) + { + return 0; + } + + return m_ADSPModes[ModeID]->ModeProcess(ArrayIn, ArrayOut, Samples); +} + +unsigned int CADSPStream::ProcessMode(AE_DSP_MODE_TYPE ModeType, float **ArrayIn, float **ArrayOut, unsigned int Samples) +{ + IADSPMode *mode = GetSingleMode(ModeType); + if (!mode) + { + return 0; + } + + return mode->ModeProcess(ArrayIn, ArrayOut, Samples); +} + +// TODO: implement common buffer for input process +unsigned int CADSPStream::ProcessMode(AE_DSP_MODE_TYPE ModeType, const float **Array_in, unsigned int Samples) +{ + return Samples; +} + +unsigned int CADSPStream::NeededSamplesize(unsigned int ModeID) +{ + if (ModeID >= m_MaxADSPModes) + { + return 0; + } + + return m_ADSPModes[ModeID]->NeededSamplesize(); +} + +unsigned int CADSPStream::NeededSamplesize(AE_DSP_MODE_TYPE ModeType) +{ + IADSPMode *mode = GetSingleMode(ModeType); + if (!mode) + { + return 0; + } + + return mode->NeededSamplesize(); +} + +float CADSPStream::GetDelay(unsigned int ModeID) +{ + if (ModeID >= m_MaxADSPModes) + { + return 0; + } + + return m_ADSPModes[ModeID]->GetDelay(); +} + +float CADSPStream::GetDelay(AE_DSP_MODE_TYPE ModeType) +{ + IADSPMode *mode = GetSingleMode(ModeType); + if (!mode) + { + return 0; + } + + return mode->GetDelay(); +} + + +int CADSPStream::MasterProcessGetOutChannels(unsigned long &OutChannelFlags) +{ + if (m_CurrentMasterMode) + { + return m_CurrentMasterMode->MasterProcessGetOutChannels(OutChannelFlags); + } + + OutChannelFlags = AE_DSP_PRSNT_CH_UNDEFINED; + return 0; +} + +const char* CADSPStream::MasterProcessGetStreamInfoString() +{ + if (m_CurrentMasterMode) + { + return m_CurrentMasterMode->MasterProcessGetStreamInfoString(); + } + + return NULL; +} + +AE_DSP_ERROR CADSPStream::MasterProcessSetMode(AE_DSP_STREAMTYPE StreamType, unsigned int ModeID, int UniqueDBModeID) +{ + if (ModeID >= m_MaxADSPModes) + { + return AE_DSP_ERROR_FAILED; + } + + return AE_DSP_ERROR_NO_ERROR; +} + + +int CADSPStream::ResamplingRate(AE_DSP_MODE_TYPE ModeType) +{ + switch (ModeType) + { + case AE_DSP_MODE_TYPE_INPUT_RESAMPLE: + { + if (m_CurrentInputResampleMode) + { + return m_CurrentInputResampleMode->ResamplingRate(); + } + } + break; + + case AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE: + if (m_CurrentInputResampleMode) + { + return m_CurrentOutputResampleMode->ResamplingRate(); + } + break; + } + + return 0; +} diff --git a/adsp.template/AudioDSP/Streams/ADSPStream.hpp b/adsp.template/AudioDSP/Streams/ADSPStream.hpp new file mode 100644 index 0000000..9ab192c --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStream.hpp @@ -0,0 +1,94 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include + +#include + +#include "AudioDSP/FactoryADSPModes/IADSPMode.hpp" + +class IADSPStreamBuilder; + + +class CADSPStream +{ + friend class IADSPStreamBuilder; + +public: + typedef std::vector ADSPModeVector_t; + + CADSPStream(); + ~CADSPStream(); + + AE_DSP_ERROR Create(const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties); + AE_DSP_ERROR Destroy(); + + AE_DSP_ERROR StreamIsModeSupported(AE_DSP_MODE_TYPE ModeType, unsigned int ModeID, int UniqueDBModeID); + + unsigned int ProcessMode(unsigned int ModeID, float **ArrayIn, float **ArrayOut, unsigned int Samples); + unsigned int ProcessMode(AE_DSP_MODE_TYPE ModeType, float **ArrayIn, float **ArrayOut, unsigned int Samples); + unsigned int ProcessMode(AE_DSP_MODE_TYPE ModeType, const float **Array_in, unsigned int Samples); + + unsigned int NeededSamplesize(unsigned int ModeID); + unsigned int NeededSamplesize(AE_DSP_MODE_TYPE ModeType); + float GetDelay(unsigned int ModeID); + float GetDelay(AE_DSP_MODE_TYPE ModeType); + + // Optional Methods for Master Modes + int MasterProcessGetOutChannels(unsigned long &OutChannelFlags); + const char* MasterProcessGetStreamInfoString(); + AE_DSP_ERROR MasterProcessSetMode(AE_DSP_STREAMTYPE StreamType, unsigned int ModeID, int UniqueDBModeID); + + // Optional Resampling Methods + int ResamplingRate(AE_DSP_MODE_TYPE ModeType); + +private: + // Gets current active master, input- or output-resampling process by mode type + inline IADSPMode* GetSingleMode(AE_DSP_MODE_TYPE ModeType) + { + IADSPMode *mode = NULL; + switch (ModeType) + { + case AE_DSP_MODE_TYPE_INPUT_RESAMPLE: + mode = m_CurrentInputResampleMode; + break; + + case AE_DSP_MODE_TYPE_MASTER_PROCESS: + mode = m_CurrentMasterMode; + break; + + case AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE: + mode = m_CurrentOutputResampleMode; + break; + } + + return mode; + } + + ADSPModeVector_t m_ADSPModeVector; + unsigned int m_MaxADSPModes; + IADSPMode **m_ADSPModes; + IADSPMode *m_CurrentMasterMode; + IADSPMode *m_CurrentInputResampleMode; + IADSPMode *m_CurrentOutputResampleMode; +}; diff --git a/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.cpp b/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.cpp new file mode 100644 index 0000000..02e79cb --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "AudioDSP/Streams/ADSPStreamBuilderAll.hpp" +#include "AudioDSP/Streams/ADSPStream.hpp" + +#include "AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp" + +#include "Addon/MessageSystem/Communication/MessageDispatcher.hpp" + +#include "Addon/Process//AddonProcessManager.hpp" + +#include "include/client.h" + +using namespace ADDON; + + +CADSPStreamBuilderAll::CADSPStreamBuilderAll() +{ +} + +CADSPStreamBuilderAll::~CADSPStreamBuilderAll() +{ +} + + +AE_DSP_ERROR CADSPStreamBuilderAll::ConstructStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties) +{ + CADSPStream::ADSPModeVector_t& modeVector = CADSPStreamAccessor::m_ADSPModeVector(ADSPStream); + + CFactoryADSPModes::ADSPModeInfoVector_t modeInfos; + CFactoryADSPModes::GetAvailableModes(modeInfos); + + for (CFactoryADSPModes::ADSPModeInfoVector_t::iterator iter = modeInfos.begin(); iter != modeInfos.end(); ++iter) + { + IADSPMode* mode = NULL; + AE_DSP_ERROR err = CFactoryADSPModes::Create(iter->ModeInfo.ModeID, iter->ModeInfo.ModeType, mode); + + if (err == AE_DSP_ERROR_NO_ERROR) + { + err = mode->Create(Settings, pProperties); + if (err == AE_DSP_ERROR_NO_ERROR) + { + modeVector.push_back(mode); + // TODO implement functionality to send messages before dispatcher gets connected to other dispatchers + //MVCObject *object = dynamic_cast(mode); + //if (object) + //{ // when this mode can be casted to CMessageDispatcher + // // notify all created addon processes about this new dispatcher + // CAddonProcessManager::ConnectObject(object); // TODO: check return value + //} + } + else + { + KODI->Log(LOG_ERROR, "%s, %i, Failed to create AudioDSP mode \"%s\"", __FUNCTION__, __LINE__, iter->ModeName.c_str()); + } + } + else + { + KODI->Log(LOG_ERROR, "%s, %i, Failed to get AudioDSP mode \"%s\"", __FUNCTION__, __LINE__, iter->ModeName.c_str()); + } + } + + if (modeVector.size() <= 0) + { + KODI->Log(LOG_ERROR, "%s, %i, Failed to create entire Stream!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_FAILED; + } + + CADSPStreamAccessor::m_MaxADSPModes(ADSPStream) = modeVector.size(); + CADSPStreamAccessor::m_ADSPModes(ADSPStream) = modeVector.data(); + + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStreamBuilderAll::InitializeStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings) +{ + CADSPStream::ADSPModeVector_t& modeVector = CADSPStreamAccessor::m_ADSPModeVector(ADSPStream); + if (modeVector.size() <= 0) + { + return AE_DSP_ERROR_FAILED; + } + + for (CADSPStream::ADSPModeVector_t::iterator iter = modeVector.begin(); iter != modeVector.end(); ++iter) + { + AE_DSP_ERROR err = (*iter)->Initialize(Settings); + if (err != AE_DSP_ERROR_NO_ERROR) + { + return err; + } + } + + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStreamBuilderAll::AddMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode) +{ + return AE_DSP_ERROR_NO_ERROR; +} + +AE_DSP_ERROR CADSPStreamBuilderAll::AddMode(CADSPStream &ADSPStream, unsigned int ModeID) +{ + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStreamBuilderAll::RemoveMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode) +{ + return AE_DSP_ERROR_NO_ERROR; +} + +AE_DSP_ERROR CADSPStreamBuilderAll::RemoveMode(CADSPStream &ADSPStream, unsigned int ModeID) +{ + return AE_DSP_ERROR_NO_ERROR; +} diff --git a/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.hpp b/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.hpp new file mode 100644 index 0000000..a71bac1 --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStreamBuilderAll.hpp @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "AudioDSP/Streams/IADSPStreamBuilder.hpp" + + +class CADSPStreamBuilderAll : public IADSPStreamBuilder +{ +public: + CADSPStreamBuilderAll(); + ~CADSPStreamBuilderAll(); + + virtual AE_DSP_ERROR ConstructStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties); + virtual AE_DSP_ERROR InitializeStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings); + + virtual AE_DSP_ERROR AddMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode); + virtual AE_DSP_ERROR AddMode(CADSPStream &ADSPStream, unsigned int ModeID); + + virtual AE_DSP_ERROR RemoveMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode); + virtual AE_DSP_ERROR RemoveMode(CADSPStream &ADSPStream, unsigned int ModeID); +}; diff --git a/adsp.template/AudioDSP/Streams/ADSPStreamManager.cpp b/adsp.template/AudioDSP/Streams/ADSPStreamManager.cpp new file mode 100644 index 0000000..d049054 --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStreamManager.cpp @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "KodiThreads/threads/SingleLock.h" + +#include "ADSPStreamManager.hpp" +#include "AudioDSP/FactoryADSPModes/FactoryADSPModes.hpp" +#include "include/client.h" + +using namespace ADDON; + + +int CADSPStreamManager::m_HasProcesses; +CADSPStream *CADSPStreamManager::m_ADSPStreams[AE_DSP_STREAM_MAX_STREAMS]; +CCriticalSection CADSPStreamManager::m_Lock; +IADSPStreamBuilder *CADSPStreamManager::m_ADSPStreamBuilder; +CADSPStreamBuilderAll CADSPStreamManager::m_ADSPStreamBuilderAll; + + +AE_DSP_ERROR CADSPStreamManager::Create() +{ + m_ADSPStreamBuilder = &m_ADSPStreamBuilderAll; + m_HasProcesses = 0; + + CFactoryADSPModes::ADSPModeInfoVector_t adspModes; + AE_DSP_ERROR err = CFactoryADSPModes::GetAvailableModes(adspModes); + + if (adspModes.size() <= 0) + { + return AE_DSP_ERROR_FAILED; + } + + KODI->Log(LOG_DEBUG, "%s, %i, Available ADSP Modes:", __FUNCTION__, __LINE__); + + for (size_t ii = 0; ii < adspModes.size(); ii++) + { + KODI->Log(LOG_DEBUG, "%s, %i, Name: %s, Internal ID: %i, ADSP Type: %i", __FUNCTION__, __LINE__, adspModes[ii].ModeName.c_str(), adspModes[ii].ModeInfo.ModeID, adspModes[ii].ModeInfo.ModeType); + if (adspModes[ii].ModeInfo.ModeType >= 0) + { + m_HasProcesses |= 1 << adspModes[ii].ModeInfo.ModeType; + } + + AE_DSP_MODES::AE_DSP_MODE adspModeSettings; + AE_DSP_ERROR err = CFactoryADSPModes::GetADSPModeSettings(adspModes[ii].ModeInfo.ModeID, adspModes[ii].ModeInfo.ModeType, adspModeSettings); + if (err == AE_DSP_ERROR_NO_ERROR) + { + KODI->Log(LOG_DEBUG, "%s, %i, Try to register ADSP Mode: %s", __FUNCTION__, __LINE__, adspModes[ii].ModeName.c_str()); + ADSP->RegisterMode(&adspModeSettings); + } + else + { + KODI->Log(LOG_ERROR, "%s, %i, Failed to retrieve ADSP Mode settings for %s", __FUNCTION__, __LINE__, adspModes[ii].ModeName.c_str()); + return AE_DSP_ERROR_FAILED; + } + } + + // set all streams to NULL + for (int st = 0; st < AE_DSP_STREAM_MAX_STREAMS; st++) + { + m_ADSPStreams[st] = NULL; + } + + return AE_DSP_ERROR_NO_ERROR; +} + + +void CADSPStreamManager::Destroy() +{ + for (int ii = 0; ii < AE_DSP_STREAM_MAX_STREAMS; ii++) + { + StreamDestroy(ii); + } +} + +AE_DSP_ERROR CADSPStreamManager::StreamIsModeSupported(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, unsigned int ModeID, int UniqueDBModeID) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_UNKNOWN; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_UNKNOWN; + } + + return m_ADSPStreams[streamID]->StreamIsModeSupported(ModeType, ModeID, UniqueDBModeID); +} + +unsigned int CADSPStreamManager::ProcessMode(const ADDON_HANDLE Handle, unsigned int ModeID, float **Array_in, float **Array_out, unsigned int Samples) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return 0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->ProcessMode(ModeID, Array_in, Array_out, Samples); +} + +unsigned int CADSPStreamManager::ProcessMode(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, float **Array_in, float **Array_out, unsigned int Samples) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return 0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->ProcessMode(ModeType, Array_in, Array_out, Samples); +} + +unsigned int CADSPStreamManager::ProcessMode(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, const float **Array_in, unsigned int Samples) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return 0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->ProcessMode(ModeType, Array_in, Samples); +} + +unsigned int CADSPStreamManager::NeededSamplesize(const ADDON_HANDLE Handle, unsigned int ModeID) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return 0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->NeededSamplesize(ModeID); +} + +unsigned int CADSPStreamManager::NeededSamplesize(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return 0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->NeededSamplesize(ModeType); +} + + +float CADSPStreamManager::GetDelay(const ADDON_HANDLE Handle, unsigned int ModeID) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return -1.0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->GetDelay(ModeID); +} + +float CADSPStreamManager::GetDelay(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return -1.0; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->GetDelay(ModeType); +} + +int CADSPStreamManager::MasterProcessGetOutChannels(const ADDON_HANDLE Handle, unsigned long &OutChannelFlags) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return -1; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->MasterProcessGetOutChannels(OutChannelFlags); +} + +const char* CADSPStreamManager::MasterProcessGetStreamInfoString(const ADDON_HANDLE Handle) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return NULL; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return 0; + } + + return m_ADSPStreams[streamID]->MasterProcessGetStreamInfoString(); +} + +AE_DSP_ERROR CADSPStreamManager::MasterProcessSetMode(const ADDON_HANDLE Handle, AE_DSP_STREAMTYPE ModeType, unsigned int ModeID, int UniqueDBModeID) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_UNKNOWN; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_UNKNOWN; + } + + return m_ADSPStreams[streamID]->MasterProcessSetMode(ModeType, ModeID, UniqueDBModeID); +} + +int CADSPStreamManager::ResamplingRate(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType) +{ + const unsigned int streamID = Handle->dataIdentifier; + if (streamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return -1; + } + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[streamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Tried to process uncreated stream!", __FUNCTION__, __LINE__); + return -1; + } + + return m_ADSPStreams[streamID]->ResamplingRate(ModeType); +} + + +AE_DSP_ERROR CADSPStreamManager::StreamCreate(const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties, const ADDON_HANDLE handle) +{ + const unsigned int iStreamID = Settings->iStreamID; + if (iStreamID >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, Invalid input! StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!", __FUNCTION__, __LINE__); + return AE_DSP_ERROR_UNKNOWN; + } + + CADSPStream *adspStream = new CADSPStream; + AE_DSP_ERROR err = m_ADSPStreamBuilder->ConstructStream(*adspStream, Settings, pProperties); + if (err != AE_DSP_ERROR_NO_ERROR) + { + delete adspStream; + KODI->Log(LOG_ERROR, "%s, %i, Requested stream: %i creation failed!", __FUNCTION__, __LINE__, iStreamID); + + return err; + } + + CSingleLock lock(m_Lock); + if (m_ADSPStreams[iStreamID]) + { + delete m_ADSPStreams[iStreamID]; + m_ADSPStreams[iStreamID] = NULL; + } + + m_ADSPStreams[iStreamID] = adspStream; + handle->dataIdentifier = iStreamID; + handle->dataAddress = NULL; + handle->callerAddress = m_ADSPStreams[iStreamID]; + + return AE_DSP_ERROR_NO_ERROR; +} + + +AE_DSP_ERROR CADSPStreamManager::StreamInitialize(const ADDON_HANDLE handle, const AE_DSP_SETTINGS *Settings) +{ + KODI->Log(LOG_DEBUG, "%s, %i, Called.", __FUNCTION__, __LINE__); + + // TODO: wait add wait for async stream creation + const unsigned int iStreamID = Settings->iStreamID; + + CSingleLock lock(m_Lock); + if (!m_ADSPStreams[iStreamID]) + { + KODI->Log(LOG_ERROR, "%s, %i, Requested stream: %i was not created! Consquently initialization of this stream failed!", __FUNCTION__, __LINE__, iStreamID); + return AE_DSP_ERROR_FAILED; + } + + return m_ADSPStreamBuilder->InitializeStream(*m_ADSPStreams[iStreamID], Settings); +} + +AE_DSP_ERROR CADSPStreamManager::StreamDestroy(unsigned int Id) +{ + if (Id >= AE_DSP_STREAM_MAX_STREAMS) + { + KODI->Log(LOG_ERROR, "%s, %i, StreamID was equal or greater than AE_DSP_STREAM_MAX_STREAMS!"); + return AE_DSP_ERROR_UNKNOWN; + } + + if (Id >= AE_DSP_STREAM_MAX_STREAMS) + { + return AE_DSP_ERROR_INVALID_PARAMETERS; + } + + CSingleLock lock(m_Lock); + if (m_ADSPStreams[Id]) + { + m_ADSPStreams[Id]->Destroy(); + + delete m_ADSPStreams[Id]; + m_ADSPStreams[Id] = NULL; + } + + return AE_DSP_ERROR_NO_ERROR; +} + + +bool CADSPStreamManager::SupportsInputProcess() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_MAX) ? true : false;; +} + +bool CADSPStreamManager::SupportsPreProcess() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_PRE_PROCESS) ? true : false;; +} + +bool CADSPStreamManager::SupportsMasterProcess() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_MASTER_PROCESS) ? true : false; +} + +bool CADSPStreamManager::SupportsPostProcess() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_POST_PROCESS) ? true : false;; +} + +bool CADSPStreamManager::SupportsInputResample() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_INPUT_RESAMPLE) ? true : false; +} + +bool CADSPStreamManager::SupportsOutputResample() +{ + return m_HasProcesses & (1 << AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE) ? true : false; +} diff --git a/adsp.template/AudioDSP/Streams/ADSPStreamManager.hpp b/adsp.template/AudioDSP/Streams/ADSPStreamManager.hpp new file mode 100644 index 0000000..e6c189a --- /dev/null +++ b/adsp.template/AudioDSP/Streams/ADSPStreamManager.hpp @@ -0,0 +1,114 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include "KodiThreads/threads/SingleLock.h" + +#include "AudioDSP/Streams/ADSPStream.hpp" +#include "AudioDSP/Streams/IADSPStreamBuilder.hpp" +#include "AudioDSP/Streams/ADSPStreamBuilderAll.hpp" + +class CADSPStreamManager +{ +public: + static AE_DSP_ERROR Create(); + static void Destroy(); + +// stream methods + static AE_DSP_ERROR StreamIsModeSupported(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, unsigned int ModeID, int UniqueDBModeID); + + static unsigned int ProcessMode(const ADDON_HANDLE Handle, unsigned int Mode_id, float **Array_in, float **Array_out, unsigned int Samples); + static unsigned int ProcessMode(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, float **Array_in, float **Array_out, unsigned int Samples); + static unsigned int ProcessMode(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType, const float **Array_in, unsigned int Samples); + + static unsigned int NeededSamplesize(const ADDON_HANDLE Handle, unsigned int ModeID); + static unsigned int NeededSamplesize(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType); + static float GetDelay(const ADDON_HANDLE Handle, unsigned int ModeID); + static float GetDelay(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType); + +// Optional Methods for Master Modes + static int MasterProcessGetOutChannels(const ADDON_HANDLE Handle, unsigned long &OutChannelFlags); + static const char* MasterProcessGetStreamInfoString(const ADDON_HANDLE Handle); + static AE_DSP_ERROR MasterProcessSetMode(const ADDON_HANDLE Handle, AE_DSP_STREAMTYPE StreamType, unsigned int ModeID, int UniqueDBModeID); + +// Optional Resampling Methods + static int ResamplingRate(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE ModeType); + + + /*! + * Control function for start and stop of dsp processing. + */ + static AE_DSP_ERROR StreamCreate(const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties, const ADDON_HANDLE handle); + static AE_DSP_ERROR StreamInitialize(const ADDON_HANDLE Handle, const AE_DSP_SETTINGS *AddonSettings); + static AE_DSP_ERROR StreamDestroy(unsigned int Id); + + ///*! + //* initialize or destroy methods for the AddonHandler + //*/ + //void Destroy(); + //bool Init(); + + /*! + * Supported processing methods + */ + static bool SupportsInputProcess(); + static bool SupportsPreProcess(); + static bool SupportsMasterProcess(); + static bool SupportsPostProcess(); + static bool SupportsInputResample(); + static bool SupportsOutputResample(); + + ///*! + //* Get Stream + //*/ + //CADSPProcessorHandle *GetStream(AE_DSP_STREAM_ID Id); + + //! This gets the current stream Id settings and properties. + /*! + * Get stream settings and properties. For details see and AE_DSP_STREAM_PROPERTIES structures. + * If the add-on operate with buffered arrays and the output size can be higher as + * the input it becomes asked about needed size before any PostProcess call. + * @param Id The requested stream id. Never use a Id equal or greater than AE_DSP_STREAM_MAX_STREAMS. + * @param pSettings Stream settings for details see AE_DSP_SETTINGS. + * @param pProperties Stream properties for details see AE_DSP_STREAM_PROPERTIES. + * @return AE_DSP_ERROR_INVALID_PARAMETERS: if your input parameters were invalid. + * AE_DSP_ERROR_REJECTED: when the requested Stream Id is not active. + * AE_DSP_ERROR_NO_ERROR: if all was ok. + */ + //AE_DSP_ERROR GetStreamInfos(AE_DSP_STREAM_ID Id, const AE_DSP_SETTINGS *pSettings, const AE_DSP_STREAM_PROPERTIES* pProperties, void *CustomStreamInfos = NULL); + + //AE_DSP_ERROR SendMessageToStream(/*CADSPModeMessage &Message*/); + + +private: + static int m_HasProcesses; + + /*! + * Pointer array for active dsp processing classes, for this reason the + * stream id is never more as AE_DSP_STREAM_MAX_STREAMS and can be used as pointer to this array. + */ + static CADSPStream *m_ADSPStreams[AE_DSP_STREAM_MAX_STREAMS]; + static CCriticalSection m_Lock; // Lock for access to m_ADSPStreams + static IADSPStreamBuilder *m_ADSPStreamBuilder; + static CADSPStreamBuilderAll m_ADSPStreamBuilderAll; +}; diff --git a/adsp.template/AudioDSP/Streams/IADSPStreamBuilder.hpp b/adsp.template/AudioDSP/Streams/IADSPStreamBuilder.hpp new file mode 100644 index 0000000..3a0d1b4 --- /dev/null +++ b/adsp.template/AudioDSP/Streams/IADSPStreamBuilder.hpp @@ -0,0 +1,61 @@ +#pragma once +/* + * Copyright (C) 2005-2016 Team Kodi + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include + +#include "ADSPStream.hpp" +#include "AudioDSP/FactoryADSPModes/IADSPMode.hpp" + + +class IADSPStreamBuilder +{ +public: + virtual AE_DSP_ERROR ConstructStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings, const AE_DSP_STREAM_PROPERTIES *pProperties) = 0; + virtual AE_DSP_ERROR InitializeStream(CADSPStream &ADSPStream, const AE_DSP_SETTINGS *Settings) = 0; + + virtual AE_DSP_ERROR AddMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode) = 0; + virtual AE_DSP_ERROR AddMode(CADSPStream &ADSPStream, unsigned int ModeID) = 0; + + virtual AE_DSP_ERROR RemoveMode(CADSPStream &ADSPStream, IADSPMode *ADSPMode) = 0; + virtual AE_DSP_ERROR RemoveMode(CADSPStream &ADSPStream, unsigned int ModeID) = 0; + +protected: + class CADSPStreamAccessor + { + public: + static inline CADSPStream::ADSPModeVector_t& m_ADSPModeVector(CADSPStream &ADSPStream) + { + return ADSPStream.m_ADSPModeVector; + } + + static inline unsigned int& m_MaxADSPModes(CADSPStream &ADSPStream) + { + return ADSPStream.m_MaxADSPModes; + } + + static inline IADSPMode**& m_ADSPModes(CADSPStream &ADSPStream) + { + return ADSPStream.m_ADSPModes; + } + }; +}; diff --git a/adsp.template/GUIDialogBase.cpp b/adsp.template/GUIDialogBase.cpp new file mode 100644 index 0000000..2e96e05 --- /dev/null +++ b/adsp.template/GUIDialogBase.cpp @@ -0,0 +1,85 @@ +#include "include/GUIDialogBase.h" +using namespace std; +using namespace ADDON; + +CGUIDialogBase::CGUIDialogBase( std::string xmlFilename, bool ForceFallback, bool AsDialog, std::string DefaultSkin ) +{ + m_window = GUI->Window_create( xmlFilename.c_str(), + DefaultSkin.c_str(), + ForceFallback, + AsDialog ); + if(m_window) + { + m_window->m_cbhdl = this; + m_window->CBOnInit = OnInitCB; + m_window->CBOnFocus = OnFocusCB; + m_window->CBOnClick = OnClickCB; + m_window->CBOnAction = OnActionCB; + } + else + { + KODI->Log( LOG_ERROR, "Couldn't create m_window! Not enough free memory?" ); + } +} + +CGUIDialogBase::~CGUIDialogBase() +{ + if(m_window) + { + GUI->Window_destroy(m_window); + } +} + +bool CGUIDialogBase::OnInitCB(GUIHANDLE cbhdl) +{ + CGUIDialogBase *dialog = static_cast(cbhdl); + return dialog->OnInit(); +} + +bool CGUIDialogBase::OnClickCB(GUIHANDLE cbhdl, int controlId) +{ + CGUIDialogBase *dialog = static_cast(cbhdl); + return dialog->OnClick(controlId); +} + +bool CGUIDialogBase::OnFocusCB(GUIHANDLE cbhdl, int controlId) +{ + CGUIDialogBase *dialog = static_cast(cbhdl); + return dialog->OnFocus(controlId); +} + +bool CGUIDialogBase::OnActionCB(GUIHANDLE cbhdl, int actionId) +{ + CGUIDialogBase *dialog = static_cast(cbhdl); + return dialog->OnAction(actionId); +} + +bool CGUIDialogBase::Show() +{ + if (m_window) + { + return m_window->Show(); + } + else + { + return false; + } +} + +void CGUIDialogBase::Close() +{ + if (m_window) + { + m_window->Close(); + } + + OnClose(); +} + +void CGUIDialogBase::DoModal() +{ + if (m_window) + { + m_window->DoModal(); + } +} diff --git a/adsp.template/Settings/ISettingsElement.h b/adsp.template/Settings/ISettingsElement.h new file mode 100644 index 0000000..f7bc177 --- /dev/null +++ b/adsp.template/Settings/ISettingsElement.h @@ -0,0 +1,64 @@ +#pragma once +/* Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "../AddonExceptions/TAddonException.h" + +class ISettingsElement +{ +public: + typedef enum + { + UNKNOWN_SETTING = -1, + STRING_SETTING, + UNSIGNED_INT_SETTING, + INT_SETTING, + FLOAT_SETTING, + DOUBLE_SETTING, + BOOL_SETTING, + MAX_SETTING + }SettingsTypes; + + ISettingsElement(std::string Key, SettingsTypes Type) + { + if(Type <= UNKNOWN_SETTING || Type >= MAX_SETTING) + { + throw ADDON_STRING_EXCEPTION_HANDLER("Requested unsupported settings type!"); + } + + if(Key.empty() || Key == "") + { + throw ADDON_STRING_EXCEPTION_HANDLER("Invalid Key used!"); + } + + m_Type = Type; + m_Key = Key; + } + + virtual ~ISettingsElement() {} + + SettingsTypes get_Type() { return m_Type; } + std::string get_Key() { return m_Key; } + +private: + SettingsTypes m_Type; + std::string m_Key; +}; diff --git a/adsp.template/Settings/SettingsHelpers.cpp b/adsp.template/Settings/SettingsHelpers.cpp new file mode 100644 index 0000000..587274d --- /dev/null +++ b/adsp.template/Settings/SettingsHelpers.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include "SettingsHelpers.h" + +using namespace std; + + +CSettingsHelpers::CSettingsHelpers() +{ +} + +CSettingsHelpers::~CSettingsHelpers() +{ +} + +string CSettingsHelpers::TranslateTypeEnumToStr(ISettingsElement::SettingsTypes eType) +{ + string type = "Unknown"; + + switch(eType) + { + case ISettingsElement::STRING_SETTING: + type = "string"; + break; + + case ISettingsElement::UNSIGNED_INT_SETTING: + type = "unsigned int"; + break; + + case ISettingsElement::INT_SETTING: + type = "int"; + break; + + case ISettingsElement::FLOAT_SETTING: + type = "float"; + break; + + case ISettingsElement::DOUBLE_SETTING: + type = "double"; + break; + + case ISettingsElement::BOOL_SETTING: + type = "bool"; + break; + + default: + type = "Unknown"; + break; + } + + return type; +} + +ISettingsElement::SettingsTypes CSettingsHelpers::TranslateTypeStrToEnum(string strType) +{ + ISettingsElement::SettingsTypes eType = ISettingsElement::UNKNOWN_SETTING; + + if(strType == "string") + { + eType = ISettingsElement::STRING_SETTING; + } + else if(strType == "unsigned int") + { + eType = ISettingsElement::UNSIGNED_INT_SETTING; + } + else if(strType == "int") + { + eType = ISettingsElement::INT_SETTING; + } + else if(strType == "float") + { + eType = ISettingsElement::FLOAT_SETTING; + } + else if(strType == "double") + { + eType = ISettingsElement::DOUBLE_SETTING; + } + else if(strType == "bool") + { + eType = ISettingsElement::BOOL_SETTING; + } + + return eType; +} diff --git a/adsp.template/Settings/SettingsHelpers.h b/adsp.template/Settings/SettingsHelpers.h new file mode 100644 index 0000000..774b48e --- /dev/null +++ b/adsp.template/Settings/SettingsHelpers.h @@ -0,0 +1,35 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include "ISettingsElement.h" + +class CSettingsHelpers +{ +public: + CSettingsHelpers(); + ~CSettingsHelpers(); + + static std::string TranslateTypeEnumToStr(ISettingsElement::SettingsTypes eType); + static ISettingsElement::SettingsTypes TranslateTypeStrToEnum(std::string strType); +}; diff --git a/adsp.template/Settings/SettingsManager.cpp b/adsp.template/Settings/SettingsManager.cpp new file mode 100644 index 0000000..e3a30fb --- /dev/null +++ b/adsp.template/Settings/SettingsManager.cpp @@ -0,0 +1,618 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include +#include "utils/stdStringUtils.h" +#include "SettingsHelpers.h" +#include "SettingsManager.h" +#include "../AddonExceptions/TAddonException.h" +#include "kodi/libXBMC_addon.h" +#include "exception" + +using namespace ADDON; +using namespace std; + +// helpers for XML-Files +#include +#include +typedef std::pair ATTRIBUTE_PAIR; +typedef std::list ATTRIBUTES_LIST; + +int getAttributesAsList(TiXmlElement* pElement, ATTRIBUTES_LIST &AttributesList); + + +CSettingsManager::CSettingsManager(string XMLFilename, string Path) +{ + if(XMLFilename == "" || XMLFilename.empty()) + { + throw ADDON_STRING_EXCEPTION_HANDLER("Invalid XML filename!"); + } + m_Path = Path; + m_XMLFilename = generateFilePath(m_Path, XMLFilename); + KODI->Log(LOG_DEBUG, "CSettingsManager will save it's XML file to: %s", m_XMLFilename.c_str()); + + m_IsSettingsXMLLoaded = false; + + m_Settings.clear(); +} + +CSettingsManager::~CSettingsManager() +{ + destroy(); +} + +void CSettingsManager::Init() +{ + if(!m_IsSettingsXMLLoaded) + { + m_IsSettingsXMLLoaded = true; + read_SettingsXML(); + } +} + +void CSettingsManager::destroy() +{ + write_SettingsXML(); + + // delete settings map and its elements + for(SettingsMap::iterator mapIter = m_Settings.begin(); mapIter != m_Settings.end(); mapIter++) + { + for(CSettingsList::iterator listIter = mapIter->second.begin(); listIter != mapIter->second.end(); listIter++) + { + ISettingsElement *settingsElement = *listIter; + if(settingsElement) + { + delete settingsElement; + *listIter = NULL; + } + } + } + + // all dynamic memory is deallocated, so we can delete the settings map + m_Settings.clear(); +} + +void CSettingsManager::write_SettingsXML() +{ + try + { + if(m_Settings.size() > 0) + { + TiXmlDocument doc; + // ToDo: check all TiXml* generations! + TiXmlDeclaration *declaration = new TiXmlDeclaration("1.0", "", ""); + doc.LinkEndChild(declaration); + TiXmlComment *autoGenComment = new TiXmlComment(); + autoGenComment->SetValue(" THIS IS A AUTO GENERTATED FILE. DO NOT EDIT! "); + doc.LinkEndChild(autoGenComment); + + for(SettingsMap::iterator mapIter = m_Settings.begin(); mapIter != m_Settings.end(); mapIter++) + { + vector tokens; + strTokenizer(mapIter->first, SETTINGS_SEPERATOR_STR, tokens); + if(tokens.size() != 3) + { + doc.Clear(); + KODI->Log(LOG_ERROR, "Line: %i func: %s, Saving XML-File failed! Wrong SettingsMap string! Please call contact Addon author!\n", __LINE__, __func__, m_XMLFilename.c_str()); + return; + } + + TiXmlElement *mainCategory = NULL; + // check if this main category is already available + for(TiXmlNode *element = doc.FirstChild(); element && !mainCategory; element = element->NextSiblingElement()) + { + if(element->Value() == tokens[0]) + { + mainCategory = static_cast(element); + } + } + + if(!mainCategory) + { // create new main category + mainCategory = new TiXmlElement(tokens[0]); + doc.LinkEndChild(mainCategory); + } + + TiXmlElement *settingsGroup = new TiXmlElement("settings_group"); + settingsGroup->SetAttribute("sub_category", tokens[1].c_str()); + settingsGroup->SetAttribute("group_name", tokens[2].c_str()); + mainCategory->LinkEndChild(settingsGroup); + + for(CSettingsList::iterator setIter=mapIter->second.begin(); setIter != mapIter->second.end(); setIter++) + { + if(!*setIter) + { + KODI->Log(LOG_ERROR, "Line: %i func: %s, invalid settings element! Please call contact Addon author!\n", __LINE__, __func__); + return; + } + TiXmlElement *setting = new TiXmlElement("setting"); + setting->SetAttribute("key", (*setIter)->get_Key().c_str()); + + switch((*setIter)->get_Type()) + { + case ISettingsElement::STRING_SETTING: + setting->SetAttribute("string", STRING_SETTINGS(*setIter)->get_Setting().c_str()); + break; + + case ISettingsElement::UNSIGNED_INT_SETTING: + setting->SetAttribute("unsigned_int", toString(UNSIGNED_INT_SETTINGS(*setIter)->get_Setting()).c_str()); + break; + + case ISettingsElement::INT_SETTING: + setting->SetAttribute("int", INT_SETTINGS(*setIter)->get_Setting()); + break; + + case ISettingsElement::FLOAT_SETTING: + setting->SetDoubleAttribute("float", (double)FLOAT_SETTINGS(*setIter)->get_Setting()); + break; + + case ISettingsElement::DOUBLE_SETTING: + setting->SetDoubleAttribute("double", DOUBLE_SETTINGS(*setIter)->get_Setting()); + break; + + case ISettingsElement::BOOL_SETTING: + if(BOOL_SETTINGS(*setIter)->get_Setting()) + { + setting->SetAttribute("bool", "true"); + } + else + { + setting->SetAttribute("bool", "false"); + } + break; + + default: + KODI->Log(LOG_ERROR, "Line: %i func: %s, invalid settings type! Please call contact Addon author!\n", __LINE__, __func__); + return; + break; + } + + settingsGroup->LinkEndChild(setting); + } + } + + if(!doc.SaveFile(m_XMLFilename.c_str())) + { + KODI->Log(LOG_ERROR, "Couldn't save XML settings to file %s", m_XMLFilename.c_str()); + } + } + } + catch(bad_alloc &e) + { + KODI->Log(LOG_ERROR, "In function: %s a invalid memory allocation accured! Not enough free memory? Exception message: %s\n", __func__, e.what()); + } +} + +void CSettingsManager::read_SettingsXML() +{ + TiXmlDocument xmlDoc; + if(!xmlDoc.LoadFile(m_XMLFilename)) + { + KODI->Log(LOG_NOTICE, "No initial settings XML file found."); + return; + } + + TiXmlElement *pRootElement = xmlDoc.RootElement(); + if(!pRootElement) + { + KODI->Log(LOG_NOTICE, "Settings XML file is empty."); + return; + } + + string mainCategory = pRootElement->Value(); + for(TiXmlNode *pGroupNode = pRootElement->FirstChild(); pGroupNode != NULL; pGroupNode = pRootElement->IterateChildren(pGroupNode)) + { + if(pGroupNode->ValueStr() == "settings_group") + { + ATTRIBUTES_LIST groupAttributesList; + if(pGroupNode && pGroupNode->Type() == TiXmlNode::TINYXML_ELEMENT) + { + getAttributesAsList(pGroupNode->ToElement(), groupAttributesList); + } + + if(pGroupNode && pGroupNode->Type() == TiXmlNode::TINYXML_ELEMENT && groupAttributesList.size() == 2 && pGroupNode->ValueStr() == "settings_group") + { + string subCategory = ""; + string groupName = ""; + for(ATTRIBUTES_LIST::iterator iter = groupAttributesList.begin(); iter != groupAttributesList.end(); iter++) + { + if(iter->first == "sub_category") + { + subCategory = iter->second; + } + + if(iter->first == "group_name") + { + groupName = iter->second; + } + } + + for(TiXmlNode *pKeyNode = pGroupNode->FirstChild(); pKeyNode != NULL; pKeyNode = pGroupNode->IterateChildren(pKeyNode)) + { + if(pKeyNode && pKeyNode->Type() == TiXmlNode::TINYXML_ELEMENT && pKeyNode->ValueStr() == "setting") + { + ATTRIBUTES_LIST settingAttributesList; + if(getAttributesAsList(pKeyNode->ToElement(), settingAttributesList) == 2) + { + string key = ""; + ISettingsElement::SettingsTypes type = ISettingsElement::UNKNOWN_SETTING; + string value = ""; + for(ATTRIBUTES_LIST::iterator iter = settingAttributesList.begin(); iter != settingAttributesList.end(); iter++) + { + if(iter->first == "key") + { + key = iter->second; + } + else + { + type = CSettingsHelpers::TranslateTypeStrToEnum(iter->first); + value = iter->second; + } + } + + ISettingsElement *setting = find_Setting(mainCategory, subCategory, groupName, key); + if(setting && setting->get_Type() == type) + { + switch(type) + { + case ISettingsElement::STRING_SETTING: + STRING_SETTINGS(setting)->set_Setting(value); + break; + + case ISettingsElement::UNSIGNED_INT_SETTING: + { + unsigned int val = stringToVal(value); + UNSIGNED_INT_SETTINGS(setting)->set_Setting(val); + } + break; + + case ISettingsElement::INT_SETTING: + { + int val = stringToVal(value); + INT_SETTINGS(setting)->set_Setting(val); + } + break; + + case ISettingsElement::FLOAT_SETTING: + { + float val = stringToVal(value); + FLOAT_SETTINGS(setting)->set_Setting(val); + } + break; + + case ISettingsElement::DOUBLE_SETTING: + { + double val = stringToVal(value); + DOUBLE_SETTINGS(setting)->set_Setting(val); + } + break; + + case ISettingsElement::BOOL_SETTING: + if(value == "true" || value == "TRUE" || value == "True") + { + bool val = true; + BOOL_SETTINGS(setting)->set_Setting(val); + } + else if(value == "false" || value == "FALSE" || value == "False") + { + bool val = false; + BOOL_SETTINGS(setting)->set_Setting(val); + } + else + { + KODI->Log(LOG_ERROR, "CSettingsManager: Failed reading bool setting"); + } + break; + + default: + KODI->Log(LOG_ERROR, "CSettingsManager: Unknown settings type!"); + break; + } + } + else + { + KODI->Log(LOG_ERROR, "CSettingsManager: Read settings element does not match the created settings element type!"); + } + } + } + } + } + } + } +} + +bool CSettingsManager::add_Setting( string MainCategory, string SubCategory, + string GroupName, string Key, + ISettingsElement::SettingsTypes Type, void *Value) +{ + if(!Value) + { + KODI->Log(LOG_ERROR, "CSettingsManager: Invalid input for %s", __FUNCTION__); + return false; + } + + string settingsStr = MainCategory + SETTINGS_SEPERATOR_STR + SubCategory + SETTINGS_SEPERATOR_STR + GroupName; + SettingsMap::iterator mapIter = m_Settings.find(settingsStr); + if(mapIter != m_Settings.end()) + { // first we have to search, if the settings element is present in the founded Main- and Subcategory + CSettingsList::iterator settingsIter = mapIter->second.begin(); + while(settingsIter != mapIter->second.end() && (*settingsIter)->get_Key() != Key) + { + settingsIter++; + } + + if(settingsIter != mapIter->second.end() && (*settingsIter)->get_Key() == Key && Type == (*settingsIter)->get_Type()) + { // if the Type and Key are the same, we override the current setting with the new value + return SetNewElementValue(*settingsIter, Value); + } + } + + // No element with the requested Main- and Subcategory and Type exists + // so we create a new one + ISettingsElement *settingsElement = CSettingsManager::CreateElement(Key, Type, Value); + if(!settingsElement) + { + KODI->Log(LOG_ERROR, "CSettingsManager: Couldn't create settings element!"); + return false; + } + + if(mapIter != m_Settings.end()) + { + mapIter->second.push_back(settingsElement); + } + else + { + CSettingsList settingsList; + settingsList.push_back(settingsElement); + m_Settings[settingsStr] = settingsList; + } + + return true; +} + +ISettingsElement *CSettingsManager::CreateElement(string Key, ISettingsElement::SettingsTypes Type, void *Value) +{ + if(!Value) + { + KODI->Log(LOG_ERROR, "CSettingsManager: Invalid input for %s", __FUNCTION__); + return NULL; + } + + ISettingsElement *element = NULL; + switch(Type) + { + case ISettingsElement::STRING_SETTING: + { + string *pVal = static_cast(Value); + CStringSetting *p = new CStringSetting(*pVal, Key, Type); + + if(pVal && p) + { + element = dynamic_cast(p); + } + else + { + if(p) + { + delete p; + p = NULL; + } + } + } + break; + + case ISettingsElement::UNSIGNED_INT_SETTING: + { + unsigned int *pVal = (unsigned int*)(Value); + CUnsignedIntSetting *p = new CUnsignedIntSetting(*pVal, Key, Type); + + if(p) + { + element = dynamic_cast(p); + } + } + break; + + case ISettingsElement::INT_SETTING: + { + int *pVal = (int*)(Value); + CIntSetting *p = new CIntSetting(*pVal, Key, Type); + + if(p) + { + element = dynamic_cast(p); + } + } + break; + + case ISettingsElement::FLOAT_SETTING: + { + float *pVal = (float*)(Value); + CFloatSetting *p = new CFloatSetting(*pVal, Key, Type); + + if(p) + { + element = dynamic_cast(p); + } + } + break; + + case ISettingsElement::DOUBLE_SETTING: + { + double *pVal = (double*)(Value); + CDoubleSetting *p = new CDoubleSetting(*pVal, Key, Type); + + if(p) + { + element = dynamic_cast(p); + } + } + break; + + case ISettingsElement::BOOL_SETTING: + { + bool *pVal = (bool*)(Value); + CBoolSetting *p = new CBoolSetting(*pVal, Key, Type); + + if(p) + { + element = dynamic_cast(p); + } + } + break; + + default: + element = NULL; + break; + } + + return element; +} + +bool CSettingsManager::SetNewElementValue(ISettingsElement *Element, void *Value) +{ + if(!Element || !Value) + { + KODI->Log(LOG_ERROR, "CSettingsManager: Invalid input for %s", __FUNCTION__); + return false; + } + + switch(Element->get_Type()) + { + case ISettingsElement::STRING_SETTING: + STRING_SETTINGS(Element)->set_Setting(*static_cast(Value)); + break; + + case ISettingsElement::UNSIGNED_INT_SETTING: + UNSIGNED_INT_SETTINGS(Element)->set_Setting(*((unsigned int*)Value)); + break; + + case ISettingsElement::INT_SETTING: + INT_SETTINGS(Element)->set_Setting(*((int*)Value)); + break; + + case ISettingsElement::FLOAT_SETTING: + FLOAT_SETTINGS(Element)->set_Setting(*((float*)Value)); + break; + + case ISettingsElement::DOUBLE_SETTING: + DOUBLE_SETTINGS(Element)->set_Setting(*((double*)Value)); + break; + + case ISettingsElement::BOOL_SETTING: + BOOL_SETTINGS(Element)->set_Setting(*((bool*)Value)); + break; + + default: + return false; + break; + } + + return true; +} + +void CSettingsManager::destroy_Setting(string MainCategory, string SubCategory, string GroupName, string Key) +{ + string settingsStr = MainCategory + SETTINGS_SEPERATOR_STR + SubCategory + SETTINGS_SEPERATOR_STR + GroupName; + SettingsMap::iterator mapIter = m_Settings.find(settingsStr); + if(mapIter != m_Settings.end()) + { + CSettingsList::iterator listIter = mapIter->second.begin(); + + // search for the correct key + while(listIter != mapIter->second.end() && (*listIter)->get_Key() != Key) + { + listIter++; + } + + // if the key was found, delete this setting + if(listIter != mapIter->second.end() && (*listIter)->get_Key() != Key) + { + if(*listIter) + { + delete *listIter; + *listIter = NULL; + } + + // erase this setting from the list + mapIter->second.erase(listIter); + } + + // check if there are other settings, else delete this Main- and Subcategory + if(mapIter->second.size() <= 0) + { + m_Settings.erase(mapIter); + } + + if(listIter == mapIter->second.end()) + { + KODI->Log(LOG_NOTICE, "CSettingsManager: Requested settings element \"%s\" in method \"%s\" not found!", settingsStr.c_str(), __FUNCTION__); + } + } + else + { + KODI->Log(LOG_NOTICE, "CSettingsManager: Requested settings element \"%s\" in method \"%s\" not found!", settingsStr.c_str(), __FUNCTION__); + } +} + +ISettingsElement *CSettingsManager::find_Setting(string MainCategory, string SubCategory, string GroupName, string Key) +{ + string settingsStr = MainCategory + SETTINGS_SEPERATOR_STR + SubCategory + SETTINGS_SEPERATOR_STR + GroupName; + SettingsMap::iterator mapIter = m_Settings.end(); + if(m_Settings.size() > 0) + { + mapIter = m_Settings.find(settingsStr); + } + if(mapIter != m_Settings.end()) + { + CSettingsList::iterator listIter = mapIter->second.begin(); + + // search for the correct key + while(listIter != mapIter->second.end() && (*listIter)->get_Key() != Key) + { + listIter++; + } + + if(listIter != mapIter->second.end() && (*listIter)->get_Key() == Key) + { + return *listIter; + } + } + + KODI->Log(LOG_NOTICE, "CSettingsManager: Couldn't find requested settings element \"%s\" in method \"%s\" not found!", settingsStr.c_str(), __FUNCTION__); + return NULL; +} + + +// Helper functions for XML-Files +int getAttributesAsList(TiXmlElement* pElement, ATTRIBUTES_LIST &AttributesList) +{ + if ( !pElement ) return -1; + + for(TiXmlAttribute *pAttrib = pElement->FirstAttribute(); pAttrib != NULL; pAttrib = pAttrib->Next()) + { + AttributesList.push_back(ATTRIBUTE_PAIR(pAttrib->Name(), pAttrib->Value())); + } + + return AttributesList.size(); +} diff --git a/adsp.template/Settings/SettingsManager.h b/adsp.template/Settings/SettingsManager.h new file mode 100644 index 0000000..6a8cd18 --- /dev/null +++ b/adsp.template/Settings/SettingsManager.h @@ -0,0 +1,84 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include +#include +#include "include/client.h" + +#include "TSettingsElement.h" + +// Settings typedefs +typedef TSettingsElement CStringSetting; +typedef TSettingsElement CUnsignedIntSetting; +typedef TSettingsElement CIntSetting; +typedef TSettingsElement CFloatSetting; +typedef TSettingsElement CDoubleSetting; +typedef TSettingsElement CBoolSetting; +typedef std::list CSettingsList; + +// Settings macro helpers +#define STRING_SETTINGS(X) dynamic_cast(X) +#define UNSIGNED_INT_SETTINGS(X) dynamic_cast(X) +#define INT_SETTINGS(X) dynamic_cast(X) +#define FLOAT_SETTINGS(X) dynamic_cast(X) +#define DOUBLE_SETTINGS(X) dynamic_cast(X) +#define BOOL_SETTINGS(X) dynamic_cast(X) + +#define SETTINGS_SEPERATOR_STR "::" + +typedef std::map SettingsMap; + +class CSettingsManager +{ + public: + CSettingsManager(std::string XMLFilename, std::string Path=g_strUserPath); + ~CSettingsManager(); + // This method loads settings from an XML-File, this method can only called once during the lifetime of this object + void Init(); + // This method can create or override settings elements + bool add_Setting( std::string MainCategory, std::string SubCategory, + std::string GroupName, std::string Key, + ISettingsElement::SettingsTypes Type, void *Value); + void destroy_Setting(std::string MainCategory, std::string SubCategory, std::string GroupName, std::string Key); + ISettingsElement *find_Setting(std::string MainCategory, std::string SubCategory, std::string GroupName, std::string Key); + + // This method writes settings into the XML-File + void write_SettingsXML(); + + protected: + ISettingsElement *CreateElement(std::string Key, ISettingsElement::SettingsTypes Type, void *Value); + bool SetNewElementValue(ISettingsElement *Element, void *Value); + void destroy(); + //SettingsMap m_Settings; + SettingsMap m_Settings; + std::string m_XMLFilename; + std::string m_Path; + + // This method reads settings from the XML-File + void read_SettingsXML(); + + private: + bool m_IsSettingsXMLLoaded; + +}; diff --git a/adsp.template/Settings/TSettingsElement.h b/adsp.template/Settings/TSettingsElement.h new file mode 100644 index 0000000..c992981 --- /dev/null +++ b/adsp.template/Settings/TSettingsElement.h @@ -0,0 +1,44 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include "ISettingsElement.h" + +template +class TSettingsElement : public ISettingsElement +{ + public: + TSettingsElement(T &Value, std::string Key, SettingsTypes Type) : + ISettingsElement(Key, Type) + { + m_Value = Value; + } + + virtual ~TSettingsElement() {} + + virtual T get_Setting() { return m_Value; } + virtual void set_Setting(T &Value) { m_Value = Value; } + + protected: + T m_Value; +}; diff --git a/adsp.template/client.cpp b/adsp.template/client.cpp new file mode 100644 index 0000000..c63f9e2 --- /dev/null +++ b/adsp.template/client.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +// include kodi platform header files +#include +#include + +// include template configuration header files +#include "configuration/templateConfiguration.h" +#include "adsp.template/include/MACROHelper.h" +#include "include/checkTemplateConfig.h" + +// include adsp template specific header files +#include "include/client.h" + +#include "AudioDSP/Streams/ADSPStreamManager.hpp" +#include "Addon/Process/AddonProcessManager.hpp" +#include "EnumStrIDs.hpp" +#include "GainMode/GainModeDialog.hpp" +#include "CompressorMode/CompressorModeDialog.hpp" + +#include "KodiThreads/system.h" + +using namespace std; +using namespace ADDON; + +#ifdef TARGET_WINDOWS +#define snprintf _snprintf +#endif + +int m_iStreamsPresent = 0; +bool m_bCreated = false; +ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; + +/* User adjustable settings are saved here. + * Default values are defined inside client.h + * and exported to the other source files. + */ +std::string g_strUserPath = ""; +std::string g_strAddonPath = ""; + + +CHelper_libXBMC_addon *KODI = NULL; +CHelper_libKODI_adsp *ADSP = NULL; +CHelper_libKODI_guilib *GUI = NULL; +CHelper_libKODI_audioengine *AUDIOENGINE = NULL; + +static void loc_KodiLoggerCallback(int LogLevel, const char *format, ...) +{ +} + +extern "C" { + +void ADDON_ReadSettings(void) +{ +} + +ADDON_STATUS ADDON_Create(void* hdl, void* props) +{ + if (!hdl || !props) + { + return ADDON_STATUS_UNKNOWN; + } + + AE_DSP_PROPERTIES* adspprops = (AE_DSP_PROPERTIES*)props; + + KODI = new CHelper_libXBMC_addon; + if (!KODI->RegisterMe(hdl)) + { + SAFE_DELETE(KODI); + return ADDON_STATUS_PERMANENT_FAILURE; + } + + GUI = new CHelper_libKODI_guilib; + if (!GUI->RegisterMe(hdl)) + { + SAFE_DELETE(GUI); + SAFE_DELETE(KODI); + return ADDON_STATUS_PERMANENT_FAILURE; + } + + ADSP = new CHelper_libKODI_adsp; + if (!ADSP->RegisterMe(hdl)) + { + SAFE_DELETE(ADSP); + SAFE_DELETE(GUI); + SAFE_DELETE(KODI); + return ADDON_STATUS_PERMANENT_FAILURE; + } + + + AUDIOENGINE = new CHelper_libKODI_audioengine; + if (!AUDIOENGINE->RegisterMe(hdl)) + { + SAFE_DELETE(ADSP); + SAFE_DELETE(GUI); + SAFE_DELETE(KODI); + SAFE_DELETE(AUDIOENGINE); + return ADDON_STATUS_PERMANENT_FAILURE; + } + + KODI->Log(LOG_DEBUG, "%s, %i, - Creating Audio DSP template", __FUNCTION__, __LINE__); + SetKodiThreadsLogger(loc_KodiLoggerCallback); + + m_CurStatus = ADDON_STATUS_UNKNOWN; + g_strUserPath = adspprops->strUserPath; + g_strAddonPath = adspprops->strAddonPath; + + ADDON_ReadSettings(); + + m_CurStatus = ADDON_STATUS_OK; + if (CADSPStreamManager::Create() != AE_DSP_ERROR_NO_ERROR) + { + m_CurStatus = ADDON_STATUS_PERMANENT_FAILURE; + } + + if (CAddonProcessManager::CreateProcesses() != AE_DSP_ERROR_NO_ERROR) + { + KODI->Log(LOG_ERROR, "%s, %i, Failed to create CAddonProcessManager!", __FUNCTION__, __LINE__); + } + + m_bCreated = true; + m_iStreamsPresent = 0; + return m_CurStatus; +} + +ADDON_STATUS ADDON_GetStatus() +{ + return m_CurStatus; +} + +void ADDON_Destroy() +{ + m_bCreated = false; + m_iStreamsPresent = 0; + + CAddonProcessManager::DestroyProcesses(); + CADSPStreamManager::Destroy(); + + ReleaseKodiThreadsLogger(); + + SAFE_DELETE(ADSP); + SAFE_DELETE(GUI); + SAFE_DELETE(KODI); + SAFE_DELETE(AUDIOENGINE); + + m_CurStatus = ADDON_STATUS_UNKNOWN; +} + +bool ADDON_HasSettings() +{ +#ifdef ADSP_ADDON_USE_SETTINGS + return true; +#else + return false; +#endif +} + +unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) +{ + (void) sSet; // Remove compiler warning + return 0; +} + +ADDON_STATUS ADDON_SetSetting(const char *SettingName, const void *SettingValue) +{ + string settingName(SettingName); + if(!SettingValue) + { + return ADDON_STATUS_PERMANENT_FAILURE; + } + + return ADDON_STATUS_OK; +} + +void ADDON_Stop() +{ +} + +void ADDON_FreeSettings() +{ +} + +void ADDON_Announce(const char *Flag, const char *Sender, const char *Message, const void *Data) +{ + // Remove compiler warnings + (void) Flag; + (void) Sender; + (void) Message; + (void) Data; +} + + +/*********************************************************** + * Audio DSP Client AddOn specific public library functions + ***********************************************************/ +const char* GetAudioDSPAPIVersion(void) +{ + return KODI_AE_DSP_API_VERSION; +} + +const char* GetMinimumAudioDSPAPIVersion(void) +{ + return KODI_AE_DSP_MIN_API_VERSION; +} + +const char* GetGUIAPIVersion(void) +{ + return KODI_GUILIB_API_VERSION; +} + +const char* GetMinimumGUIAPIVersion(void) +{ + return KODI_GUILIB_MIN_API_VERSION; +} + +AE_DSP_ERROR GetAddonCapabilities(AE_DSP_ADDON_CAPABILITIES* pCapabilities) +{ + if(pCapabilities == NULL) + { + return AE_DSP_ERROR_FAILED; + } + + pCapabilities->bSupportsInputProcess = CADSPStreamManager::SupportsInputProcess(); + pCapabilities->bSupportsPreProcess = CADSPStreamManager::SupportsPreProcess(); + pCapabilities->bSupportsMasterProcess = CADSPStreamManager::SupportsMasterProcess(); + pCapabilities->bSupportsPostProcess = CADSPStreamManager::SupportsPostProcess(); + pCapabilities->bSupportsInputResample = CADSPStreamManager::SupportsInputResample(); + pCapabilities->bSupportsOutputResample = CADSPStreamManager::SupportsOutputResample(); + + return AE_DSP_ERROR_NO_ERROR; +} + +const char* GetDSPName(void) +{ + return ADSP_ADDON_NAME; +} + +const char* GetDSPVersion(void) +{ + return ADSP_ADDON_VERSION; +} + +AE_DSP_ERROR CallMenuHook(const AE_DSP_MENUHOOK& Menuhook, const AE_DSP_MENUHOOK_DATA &Item) +{ + // TODO implement an generic interface to open any kind of dialogs + if (Menuhook.iHookId == CADSPModeIDs::PostProcessingModeGain/* && Item.category == AE_DSP_MENUHOOK_POST_PROCESS*/) + { + CGainModeDialog dialog; + IKodiGUIView *view = dynamic_cast(&dialog); + view->DoModal(); + //view->Destroy(); + return AE_DSP_ERROR_NO_ERROR; + } + + if (Menuhook.iHookId == CADSPModeIDs::PostProcessingModeCompressor/* && Item.category == AE_DSP_MENUHOOK_POST_PROCESS*/) + { + CCompressorModeDialog dialog; + IKodiGUIView *view = dynamic_cast(&dialog); + view->DoModal(); + //view->Destroy(); + return AE_DSP_ERROR_NO_ERROR; + } + + KODI->Log(LOG_ERROR, "called unknown menu hook!"); + return AE_DSP_ERROR_FAILED; +} + + +/*! + * Control function for start and stop of dsp processing. + */ +AE_DSP_ERROR StreamCreate(const AE_DSP_SETTINGS *AddonSettings, const AE_DSP_STREAM_PROPERTIES* pProperties, ADDON_HANDLE Handle) +{ + return CADSPStreamManager::StreamCreate(AddonSettings, pProperties, Handle); +} + +AE_DSP_ERROR StreamDestroy(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::StreamDestroy(Handle->dataIdentifier); +} + +AE_DSP_ERROR StreamInitialize(const ADDON_HANDLE Handle, const AE_DSP_SETTINGS *AddonSettings) +{ + return CADSPStreamManager::StreamInitialize(Handle, AddonSettings); +} + + +/*! + * Pre processing related functions + */ +unsigned int PreProcessNeededSamplesize(const ADDON_HANDLE Handle, unsigned int Mode_id) +{ + return CADSPStreamManager::NeededSamplesize(Handle, Mode_id); +} + +float PreProcessGetDelay(const ADDON_HANDLE Handle, unsigned int Mode_id) +{ + return CADSPStreamManager::GetDelay(Handle, Mode_id); +} + +/*! + * Resampling related functions before master processing. + * only one dsp addon is allowed to do this + */ +unsigned int InputResampleProcessNeededSamplesize(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::NeededSamplesize(Handle, AE_DSP_MODE_TYPE_INPUT_RESAMPLE); +} + +int InputResampleSampleRate(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::ResamplingRate(Handle, AE_DSP_MODE_TYPE_INPUT_RESAMPLE); +} + +float InputResampleGetDelay(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::GetDelay(Handle, AE_DSP_MODE_TYPE_INPUT_RESAMPLE); +} + +/*! + * Master processing functions + * only one during playback selectable dsp addon is allowed to do this + */ +AE_DSP_ERROR MasterProcessSetMode(const ADDON_HANDLE Handle, AE_DSP_STREAMTYPE Type, unsigned int Mode_id, int Unique_db_mode_id) +{ + return CADSPStreamManager::MasterProcessSetMode(Handle, Type, Mode_id, Unique_db_mode_id); +} + +unsigned int MasterProcessNeededSamplesize(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::NeededSamplesize(Handle, AE_DSP_MODE_TYPE_MASTER_PROCESS); +} + +float MasterProcessGetDelay(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::GetDelay(Handle, AE_DSP_MODE_TYPE_MASTER_PROCESS); +} + +int MasterProcessGetOutChannels(const ADDON_HANDLE Handle, unsigned long &Out_channel_present_flags) +{ + return CADSPStreamManager::MasterProcessGetOutChannels(Handle, Out_channel_present_flags); +} + +const char *MasterProcessGetStreamInfoString(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::MasterProcessGetStreamInfoString(Handle); +} + + +/*! + * Post processing related functions + * all enabled addons allowed todo this + */ +unsigned int PostProcessNeededSamplesize(const ADDON_HANDLE Handle, unsigned int Mode_id) +{ + return CADSPStreamManager::NeededSamplesize(Handle, Mode_id); +} + +float PostProcessGetDelay(const ADDON_HANDLE Handle, unsigned int Mode_id) +{ + return CADSPStreamManager::GetDelay(Handle, Mode_id); +} + +/*! + * Resampling related functions after final processing. + * only one dsp addon is allowed to do this + */ +unsigned int OutputResampleProcessNeededSamplesize(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::NeededSamplesize(Handle, AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); +} + +int OutputResampleSampleRate(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::ResamplingRate(Handle, AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); +} + +float OutputResampleGetDelay(const ADDON_HANDLE Handle) +{ + return CADSPStreamManager::GetDelay(Handle, AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE); +} + +/*! + * Addon Processing functions + */ +bool InputProcess(const ADDON_HANDLE Handle, const float **Array_in, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, AE_DSP_MODE_TYPE_MAX, Array_in, Samples) > 0; +} + +unsigned int InputResampleProcess(const ADDON_HANDLE Handle, float **Array_in, float **Array_out, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, AE_DSP_MODE_TYPE_INPUT_RESAMPLE, Array_in, Array_out, Samples); +} + +unsigned int PreProcess(const ADDON_HANDLE Handle, unsigned int Mode_id, float **Array_in, float **Array_out, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, Mode_id, Array_in, Array_out, Samples); +} + +unsigned int MasterProcess(const ADDON_HANDLE Handle, float **Array_in, float **Array_out, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, AE_DSP_MODE_TYPE_MASTER_PROCESS, Array_in, Array_out, Samples); +} + +unsigned int PostProcess(const ADDON_HANDLE Handle, unsigned int Mode_id, float **Array_in, float **Array_out, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, Mode_id, Array_in, Array_out, Samples); +} + +unsigned int OutputResampleProcess(const ADDON_HANDLE Handle, float **Array_in, float **Array_out, unsigned int Samples) +{ + return CADSPStreamManager::ProcessMode(Handle, AE_DSP_MODE_TYPE_OUTPUT_RESAMPLE, Array_in, Array_out, Samples); +} + +AE_DSP_ERROR StreamIsModeSupported(const ADDON_HANDLE Handle, AE_DSP_MODE_TYPE Type, unsigned int Mode_id, int Unique_db_mode_id) +{ + return CADSPStreamManager::StreamIsModeSupported(Handle, Type, Mode_id, Unique_db_mode_id); +} +} diff --git a/adsp.template/configuration/templateConfiguration.h b/adsp.template/configuration/templateConfiguration.h new file mode 100644 index 0000000..ea89889 --- /dev/null +++ b/adsp.template/configuration/templateConfiguration.h @@ -0,0 +1,153 @@ +#pragma once +/* + * Copyright (C) 2005-2016 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 3, 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +//! In this file you can configure the hole template. +/*! + * \file templateConfiguration.h + * ToDo: detailed description! + */ +#include "../include/typedefs.h" + +//! Here you must define the name of the header file from your processing class. +#define ADSP_PROCESSOR_HEADER_FILE "DSPProcessor.h" +//! Here you must define the name of your ADSP addon. +#define ADSP_ADDON_NAME "AudioDSP Playground" +//! Here you must define the version of your ADSP addon. +#define ADSP_ADDON_VERSION "1.0.0" +//#define ADSP_ADDON_ID + +//optional calling methods +//! Here you can define the name of the header file for optional ADSP addon functions. +//! If you define this, then your ADSP addon can use optional functions for example +//! a settings GUI. +#define ADSP_ADDON_OPTIONAL_HEADER_FILE "ADDONOptional.h" +//! If you define this, then your ADSP addon can use settings. +#define ADSP_ADDON_USE_SETTINGS +//! This is optional and can be used to have configuration file. +#define ADSP_SETTINGS_FILE "ADSPTemplateSettings.xml" +//! If you define this, then your ADSP addon can read the saved settings. +#define ADSP_ADDON_USE_READSETTINGS +//! If you define this, then your ADSP addon can get settings from kodi. +#define ADSP_ADDON_USE_GETSETTINGS +//! ToDo! +#define ADSP_ADDON_USE_STOP +//! ToDo! +#define ADSP_ADDON_USE_FREESETTINGS +//! ToDo! +#define ADSP_ADDON_USE_ANNOUNCE +//! If you define this, then your ADSP addon can have a settings GUI for processing modes. +#define ADSP_ADDON_USE_MENUHOOK +//! If you define this, then your ADSP addon can use a optional init method and +//! kodi will call it when your ADSP is loaded the first time. +#define ADSP_ADDON_USE_OPTIONAL_INIT + + + +//--------------processing methods-------------------------------------------- +//! Define this if you wish to use input process mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::InputProcess(float **Array_in, unsigned int Samples) + * in your processing class. For details see CDSPProcessor. + */ +#define ADSP_ADDON_USE_INPUTPROCESS + +//! Define this if you wish to use input resample mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::InputResampleProcess(float **Array_in, float **Array_out, unsigned int Samples) + * in your processing class. For details see CDSPProcessor. + */ +//#define ADSP_ADDON_USE_INPUTRESAMPLE + +//! Define this if you wish to use preprocessing mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::PreProcess(unsigned int Mode_id, float **Array_in, + * float **Array_out, unsigned int Samples) + * in your processing class. For details see CDSPProcessor. + */ +#define ADSP_ADDON_USE_PREPROCESSING + +//! Define this if you wish to use master mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::MasterProcess(float **Array_in, float **Array_out, unsigned int Samples) + * in your processing class. For details see CDSPProcessor. + */ +#define ADSP_ADDON_USE_MASTERPROCESS + +//! Define this if you wish to use postprocess mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::PostProcess(unsigned int Mode_id, float **Array_in, float **Array_out, + * unsigned int Samples) in your processing class. For details see CDSPProcessor. + */ +#define ADSP_ADDON_USE_POSTPROCESS + +//! Define this if you wish to use output resample mode within your ADSP addon. +/*! + * If you define this, then your processing class must implement + * CDSPProcessor::OutputResampleProcess(float **Array_in, float **Array_out, + * unsigned int Samples) in your processing class. For details see CDSPProcessor. + */ +#define ADSP_ADDON_USE_OUTPUTRESAMPLE + +#define USE_SSE +#define USE_CUDA +#define USE_NEON + +// max processing methods +#define ADSP_MAX_INRES_MODES 1 +//! If you have defined ADSP_ADDON_USE_MASTERPROCESS, then you must define the amount +//! of available masterprocess modes of your ADSP addon. +#define ADSP_MAX_MASTER_MODES 1 +//! If you have defined ADSP_ADDON_USE_MASTERPROCESS, then you must define the amount +//! of available preprocess modes of your ADSP addon. +#define ADSP_MAX_PRE_MODES 1 +//! If you have defined ADSP_ADDON_USE_POSTPROCESS, then you must define the amount +//! of available postprocess modes of your ADSP addon. +#define ADSP_MAX_POST_MODES 1 +#define ADSP_MAX_OUTRES_MODES 1 + +//--------------general settings-------------------------------------------- +/** + * @brief Here you can define mode ids. The best practise is to use this enum, + * because a mode id should only use once in the whole ADSP addon. + */ +typedef enum +{ + PRE_MODE1_ID=0, /*!< @brief Example mode id for preprocessing mode. */ + MA_MODE1_ID, /*!< @brief Example mode id for masterprocess mode. */ + POST_MODE1_ID, /*!< @brief Example mode id for preprocessing mode. */ + INPUT_RESAMPLE_MODE_ID, + OUTPUT_RESAMPLE_MODE_ID +}adspProcessingModeIDs; + +typedef enum +{ + ID_MENU_PRE_PROCESS=1, + ID_MENU_MASTER_PROCESS, + ID_MENU_POST_PROCESS, + ID_MENU_INPUT_RESAMPLE_PROCESS, + ID_MENU_OUTPUT_RESAMPLE_PROCESS +}adspMENUIDs; \ No newline at end of file diff --git a/adsp.template/doxygenDocu.h b/adsp.template/doxygenDocu.h new file mode 100644 index 0000000..594ac68 --- /dev/null +++ b/adsp.template/doxygenDocu.h @@ -0,0 +1,90 @@ +#pragma once +/*! \mainpage XBMC ADSP Addon Handling & Template Documentation + * + * \section overview_sec Overview + * This documentation describes how to setup XBMC with + * Audio Digital Signal Processing (ADSP) addons and how to start developing for it. + * At the moment of writting there only exist a branch of XBMC for that + * (AlwinEsch's + * audio-dsp-addon-handling modification ). + * We hope that this modifications will be added to XBMC master repository very soon. + * + * \section reference_sec Reference + * - If you wanna compile XBMC with alwinus modifications see \ref how_to_compile_page.
+ * - For more informations about how to develop a ADSP addon see \ref how_to_develop_page. + * - If you wanna know how to use the ADSP addon modification in the view of an user then + * you have to follow the instructions in \ref how_to_use_adsp_addons_page. + * + * \section todo_sec Things to do + * The ADSP handling in XBMC and the template are almost finished, + * but there are things to do for more details see \ref todo. + * + * \subsection license_sec License + * @author wisler (ADSP addon developer), wislerelectronics@googlemail.com + * @author alwinus (ADSP XBMC addong handling & ADSP addon developer), email@email.com + * @date April 22, 2014 + */ + +/*! \page how_to_compile_page How to compile XBMC with ADSP addon handling + * \tableofcontents + * \section win_sec Compiling for Windows + * ToDo! + * + * \section linux_sec Compiling for Linux + * ToDo! + * + * \section mac_os_x_sec Compiling for MAC OS X + * Find someone who can compile and test XBMC with ADSP addon handling under MAC OS X. +*/ + + +/*! \page how_to_develop_page How to develop a ADSP addon for XBMC + * \tableofcontents + * \section introduction_sec Introduction + * The ADSP addon API is quite complex and the prefered way is to build the template first. + * So you can see if all is working. After that you can use the template as a starting point and + * implement your algorithm into the template. On the other hand you can write your own wrapper + * class and use the template as a reference. + * + * \section software_sec Prerequisites + * \subsection Software for Windows + * \subsection Software for Linux + * \subsection Software for MAC OS X + * \section how_to_get_ADSP_template_sec How to get ADSP addon template + * \section processing_modes_sec Processing modes + * \subsection input_processing_mode_sec Input processing mode description + * ToDo + * + * \section how_to_use_adsp_addon_sec How to use your ADSP addon + * ToDo
+ * + * \section templateConfiguration_h_sec How to configure the template + * ToDo
+ * For more details see templateConfiguration.h. + * + * \section templateConfiguration_cpp_sec How to configure processing modes + * ToDo
+ * For more details see templateConfiguration.cpp. + * + * \section own_processing_class_sec How to create your own processing class + * ToDo
+ * You can implement your own or use the CDSPProcessor class as an starting point. + * + * \section own_optional_class_sec How to create your own optional class + * ToDo
+ * You can implement your own or use the CADDONOptional class as an starting point. + * +*/ + +/*! \page how_to_use_adsp_addons_page How to use the ADSP addon handling modification (user perspective) + * \tableofcontents + * \section enable_disable_sec Enable or Disable an ADSP addon (XBMC's addon manager) + * ToDo + * + * \section DSP_manager_sec How to use the DSP Manager + * At the moment of writting the GUI is not complete. When it is finish this section will + * be extended. + * + * \section listening_mode_sec How to enable signal processing while playing media files + * ToDo +*/ \ No newline at end of file diff --git a/adsp.template/include/GUIDialogBase.h b/adsp.template/include/GUIDialogBase.h new file mode 100644 index 0000000..18794be --- /dev/null +++ b/adsp.template/include/GUIDialogBase.h @@ -0,0 +1,51 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "client.h" +#include +#include + +class CGUIDialogBase +{ +public: + CGUIDialogBase( std::string xmlFilename, bool ForceFallback, bool AsDialog, std::string DefaultSkin = "Confluence" ); + virtual ~CGUIDialogBase(); + + bool Show(); + void Close(); + void DoModal(); + +private: + static bool OnClickCB(GUIHANDLE cbhdl, int controlId); + static bool OnFocusCB(GUIHANDLE cbhdl, int controlId); + static bool OnInitCB(GUIHANDLE cbhdl); + static bool OnActionCB(GUIHANDLE cbhdl, int actionId); + +protected: + CAddonGUIWindow *m_window; // window handle + +private: // private virtual methods + virtual bool OnInit() = 0; + virtual bool OnClick(int controlId) = 0; + virtual bool OnFocus(int controlId) = 0; + virtual bool OnAction(int actionId) = 0; + virtual void OnClose() = 0; +}; diff --git a/adsp.template/include/MACROHelper.h b/adsp.template/include/MACROHelper.h new file mode 100644 index 0000000..2201e91 --- /dev/null +++ b/adsp.template/include/MACROHelper.h @@ -0,0 +1,125 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ +#include "client.h" +#include "typedefs.h" +#include "../configuration/templateConfiguration.h" + +#define USE_ADDONOPTIONAL defined(ADSP_ADDON_USE_SETTINGS) || defined(ADSP_ADDON_USE_READSETTINGS) || \ + defined(ADSP_ADDON_USE_GETSETTINGS) || defined(ADSP_ADDON_USE_STOP) || \ + defined(ADSP_ADDON_USE_FREESETTINGS) || defined(ADSP_ADDON_USE_ANNOUNCE) || \ + defined(ADSP_ADDON_USE_MENUHOOK) + +#define SIZE_OF_ARRAY(X, Y) sizeof(X)/sizeof(Y) + +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) + +#ifdef ADSP_ADDON_USE_INPUTRESAMPLE + extern ADSP_INRESMOD_UNIQUEDBID adspInResampleUniqueDdId; + extern ADSP_INRESMOD_STR_NAMES adspInResampleStrNames[AE_DSP_ADDON_STRING_LENGTH]; + + extern ADSP_INRESMOD_MODE_NUM adspInResampleModeNum; + extern ADSP_INRESMOD_TYPE_FLAGS adspInResampleTypeFlags; + extern ADSP_INRESMOD_SETTINGS_DIALOG adspInResampleSettings; + extern ADSP_INRESMOD_DISABLED adspInResampleDisabled; + + extern ADSP_INRESMOD_NAME adspInResampleName; + extern ADSP_INRESMOD_SETUP_NAME adspInResampleSetupName; + extern ADSP_INRESMOD_DESCRIPTION adspInResampleDescription; + extern ADSP_INRESMOD_HELP adspInResampleHelp; + + extern ADSP_INRESMOD_OWN_IMAGE adspInResampleOwnImage[AE_DSP_ADDON_STRING_LENGTH]; + extern ADSP_INRESMOD_OVERRIDE_IMAGE adspInResampleOverrideImage[AE_DSP_ADDON_STRING_LENGTH]; +#endif + +#ifdef ADSP_ADDON_USE_PREPROCESSING + extern ADSP_PREMOD_UNIQUEDBID adspPreUniqueDbId[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_STR_NAMES adspPreStrNames[ADSP_MAX_PRE_MODES][AE_DSP_ADDON_STRING_LENGTH]; + + extern ADSP_PREMOD_MODE_NUM adspPreModeNum[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_TYPE_FLAGS adspPreTypeFlags[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_SETTINGS_DIALOG adspPreSettings[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_DISABLED adspPreDisabled[ADSP_MAX_PRE_MODES]; + + extern ADSP_PREMOD_NAME adspPreName[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_SETUP_NAME adspPreSetupName[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_DESCRIPTION adspPreDescription[ADSP_MAX_PRE_MODES]; + extern ADSP_PREMOD_HELP adspPreHelp[ADSP_MAX_PRE_MODES]; + + extern ADSP_PREMOD_OWN_IMAGE adspPreOwnImage[ADSP_MAX_PRE_MODES][AE_DSP_ADDON_STRING_LENGTH]; + extern ADSP_PREMOD_OVERRIDE_IMAGE adspPreOverrideImage[ADSP_MAX_PRE_MODES][AE_DSP_ADDON_STRING_LENGTH]; +#endif + + +#ifdef ADSP_ADDON_USE_MASTERPROCESS + extern ADSP_MAMOD_UNIQUEDBID adspMaUniqueDdId[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_STR_NAMES adspMaStrNames[ADSP_MAX_MASTER_MODES][AE_DSP_ADDON_STRING_LENGTH]; + + extern ADSP_MAMOD_MODE_NUM adspMaModeNum[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_TYPE_FLAGS adspMaTypeFlags[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_SETTINGS_DIALOG adspMasterSettings[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_DISABLED adspMaDisabled[ADSP_MAX_MASTER_MODES]; + + extern ADSP_MAMOD_NAME adspMaName[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_SETUP_NAME adspMaSetupName[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_DESCRIPTION adspMaDescription[ADSP_MAX_MASTER_MODES]; + extern ADSP_MAMOD_HELP adspMaHelp[ADSP_MAX_MASTER_MODES]; + + extern ADSP_MAMOD_OWN_IMAGE adspMaOwnImage[ADSP_MAX_MASTER_MODES][AE_DSP_ADDON_STRING_LENGTH]; + extern ADSP_MAMOD_OVERRIDE_IMAGE adspMaOverrideImage[ADSP_MAX_MASTER_MODES][AE_DSP_ADDON_STRING_LENGTH]; +#endif + + +#ifdef ADSP_ADDON_USE_POSTPROCESS + extern ADSP_POSTMOD_UNIQUEDBID adspPostUniqueDbId[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_STR_NAMES adspPostStrNames[ADSP_MAX_POST_MODES][AE_DSP_ADDON_STRING_LENGTH]; + + extern ADSP_POSTMOD_MODE_NUM adspPostModeNum[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_TYPE_FLAGS adspPostTypeFlags[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_SETTINGS_DIALOG adspPostSettings[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_DISABLED adspPostDisabled[ADSP_MAX_POST_MODES]; + + extern ADSP_POSTMOD_NAME adspPostName[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_SETUP_NAME adspPostSetupName[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_DESCRIPTION adspPostDescription[ADSP_MAX_POST_MODES]; + extern ADSP_POSTMOD_HELP adspPostHelp[ADSP_MAX_POST_MODES]; + + extern ADSP_POSTMOD_OWN_IMAGE adspPostOwnImage[ADSP_MAX_POST_MODES][AE_DSP_ADDON_STRING_LENGTH]; + extern ADSP_POSTMOD_OVERRIDE_IMAGE adspPostOverrideImage[ADSP_MAX_POST_MODES][AE_DSP_ADDON_STRING_LENGTH]; +#endif + +#ifdef ADSP_ADDON_USE_OUTPUTRESAMPLE + extern ADSP_OUTRESMOD_UNIQUEDBID adspOutResampleUniqueDdId; + extern ADSP_OUTRESMOD_STR_NAMES adspOutResampleStrNames[AE_DSP_ADDON_STRING_LENGTH]; + + extern ADSP_OUTRESMOD_MODE_NUM adspOutResampleModeNum; + extern ADSP_OUTRESMOD_TYPE_FLAGS adspOutResampleTypeFlags; + extern ADSP_OUTRESMOD_SETTINGS_DIALOG adspOutResampleSettings; + extern ADS_OUTRESMOD_DISABLED adspOutResampleDisabled; + + extern ADSP_OUTRESMOD_NAME adspOutResampleName; + extern ADSP_OUTRESMOD_SETUP_NAME adspOutResampleSetupName; + extern ADSP_OUTRESMOD_DESCRIPTION adspOutResampleDescription; + extern ADSP_OUTRESMOD_HELP adspOutResampleHelp; + + extern ADSP_OUTRESMOD_OWN_IMAGE adspOutResampleOwnImage[AE_DSP_ADDON_STRING_LENGTH]; + extern ADSP_OUTRESMOD_OVERRIDE_IMAGE adspOutResampleOverrideImage[ADSP_MAX_OUTRES_MODES][AE_DSP_ADDON_STRING_LENGTH]; +#endif \ No newline at end of file diff --git a/adsp.template/include/checkTemplateConfig.h b/adsp.template/include/checkTemplateConfig.h new file mode 100644 index 0000000..8337230 --- /dev/null +++ b/adsp.template/include/checkTemplateConfig.h @@ -0,0 +1,37 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + + + +#ifndef ADSP_PROCESSOR_HEADER_FILE +#error "ADSP_PROCESSOR_HEADER_FILE was not defined! Please define the name of your include file in /template/configuration/templateConfiguration.h" +#endif + +#ifndef ADSP_ADDON_NAME +#error "ADSP_ADDON_NAME was not defined! Please define the the addon name in /template/configuration/templateConfiguration.h" +#endif + +#ifdef ADSP_ADDON_USE_MASTERPROCESS +#ifndef ADSP_MAX_MASTER_MODES +#error "Please define ADSP_MAX_MASTER_MODES with the number of used master processes!" +#endif +#endif \ No newline at end of file diff --git a/adsp.template/include/client.h b/adsp.template/include/client.h new file mode 100644 index 0000000..3716137 --- /dev/null +++ b/adsp.template/include/client.h @@ -0,0 +1,35 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include +#include + +extern bool m_bCreated; +extern std::string g_strUserPath; +extern std::string g_strAddonPath; +extern ADDON::CHelper_libXBMC_addon *KODI; +extern CHelper_libKODI_guilib *GUI; +extern CHelper_libKODI_adsp *ADSP; +extern CHelper_libKODI_adsp *ADSP; +extern CHelper_libKODI_audioengine *AUDIOENGINE; diff --git a/adsp.template/include/typedefs.h b/adsp.template/include/typedefs.h new file mode 100644 index 0000000..eaa197a --- /dev/null +++ b/adsp.template/include/typedefs.h @@ -0,0 +1,91 @@ +//--- typedefs input resample --- +typedef int ADSP_INRESMOD_UNIQUEDBID; +typedef char ADSP_INRESMOD_STR_NAMES; + +typedef unsigned int ADSP_INRESMOD_MODE_NUM; +typedef unsigned int ADSP_INRESMOD_TYPE_FLAGS; +typedef bool ADSP_INRESMOD_SETTINGS_DIALOG; +typedef bool ADSP_INRESMOD_DISABLED; +//typedefs for g_localizeStrings +typedef unsigned int ADSP_INRESMOD_NAME; +typedef unsigned int ADSP_INRESMOD_SETUP_NAME; +typedef unsigned int ADSP_INRESMOD_DESCRIPTION; +typedef unsigned int ADSP_INRESMOD_HELP; + +typedef char ADSP_INRESMOD_OWN_IMAGE; +typedef char ADSP_INRESMOD_OVERRIDE_IMAGE; + + +//--- typedefs preprocessing modes --- +typedef int ADSP_PREMOD_UNIQUEDBID; +typedef char ADSP_PREMOD_STR_NAMES; + +typedef unsigned int ADSP_PREMOD_MODE_NUM; +typedef unsigned int ADSP_PREMOD_TYPE_FLAGS; +typedef bool ADSP_PREMOD_SETTINGS_DIALOG; +typedef bool ADSP_PREMOD_DISABLED; +//typedefs for g_localizeStrings +typedef unsigned int ADSP_PREMOD_NAME; +typedef unsigned int ADSP_PREMOD_SETUP_NAME; +typedef unsigned int ADSP_PREMOD_DESCRIPTION; +typedef unsigned int ADSP_PREMOD_HELP; + +typedef char ADSP_PREMOD_OWN_IMAGE; +typedef char ADSP_PREMOD_OVERRIDE_IMAGE; + + +//--- typedefs master modes --- +typedef int ADSP_MAMOD_UNIQUEDBID; +typedef char ADSP_MAMOD_STR_NAMES; + +typedef unsigned int ADSP_MAMOD_MODE_NUM; +typedef unsigned int ADSP_MAMOD_TYPE_FLAGS; +typedef bool ADSP_MAMOD_SETTINGS_DIALOG; +typedef bool ADSP_MAMOD_DISABLED; +//typedefs for g_localizeStrings +typedef unsigned int ADSP_MAMOD_NAME; +typedef unsigned int ADSP_MAMOD_SETUP_NAME; +typedef unsigned int ADSP_MAMOD_DESCRIPTION; +typedef unsigned int ADSP_MAMOD_HELP; + +typedef char ADSP_MAMOD_OWN_IMAGE; +typedef char ADSP_MAMOD_OVERRIDE_IMAGE; + + +//--- typedefs postrocessing modes --- +typedef int ADSP_POSTMOD_UNIQUEDBID; +typedef char ADSP_POSTMOD_STR_NAMES; + +typedef unsigned int ADSP_POSTMOD_MODE_NUM; +typedef unsigned int ADSP_POSTMOD_TYPE_FLAGS; +typedef bool ADSP_POSTMOD_SETTINGS_DIALOG; +typedef bool ADSP_POSTMOD_DISABLED; +//typedefs for g_localizeStrings +typedef unsigned int ADSP_POSTMOD_NAME; +typedef unsigned int ADSP_POSTMOD_SETUP_NAME; +typedef unsigned int ADSP_POSTMOD_DESCRIPTION; +typedef unsigned int ADSP_POSTMOD_HELP; + +typedef char ADSP_POSTMOD_OWN_IMAGE; +typedef char ADSP_POSTMOD_OVERRIDE_IMAGE; + + +//--- typedefs postrocessing modes --- +typedef int ADSP_OUTRESMOD_UNIQUEDBID; +typedef char ADSP_OUTRESMOD_STR_NAMES; + +typedef unsigned int ADSP_OUTRESMOD_MODE_NUM; +typedef unsigned int ADSP_OUTRESMOD_TYPE_FLAGS; +typedef bool ADSP_OUTRESMOD_SETTINGS_DIALOG; +typedef bool ADS_OUTRESMOD_DISABLED; +//typedefs for g_localizeStrings +typedef unsigned int ADSP_OUTRESMOD_NAME; +typedef unsigned int ADSP_OUTRESMOD_SETUP_NAME; +typedef unsigned int ADSP_OUTRESMOD_DESCRIPTION; +typedef unsigned int ADSP_OUTRESMOD_HELP; + +typedef char ADSP_OUTRESMOD_OWN_IMAGE; +typedef char ADSP_OUTRESMOD_OVERRIDE_IMAGE; + +// general typedefs +//#define ADSP_PROCESSING_MODE_IDS typedef enum \ No newline at end of file diff --git a/adsp.template/utils/stdStringUtils.h b/adsp.template/utils/stdStringUtils.h new file mode 100644 index 0000000..4b8be79 --- /dev/null +++ b/adsp.template/utils/stdStringUtils.h @@ -0,0 +1,80 @@ +#pragma once +/* + * Copyright (C) 2005-2014 Team XBMC + * http://xbmc.org + * + * 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 3, 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 XBMC; see the file COPYING. If not, see + * . + * + */ + + + +#include +#include +#include +#include + +// convert Val to std::string +template +std::string toString(T Val) +{ + std::ostringstream oss; + oss << Val; + std::string str(oss.str()); + + return str; +} + +template +T stringToVal(std::string Str) +{ + T val; + std::istringstream(Str) >> val; + return val; +} + +inline unsigned int strTokenizer(std::string Str, std::string Delimiter, std::vector &StrTokens) +{ + unsigned int lastPos = Str.find_first_not_of(Delimiter, 0); + unsigned int pos = Str.find(Delimiter, lastPos); + + while(std::string::npos != pos || std::string::npos != lastPos) + { + StrTokens.push_back(Str.substr(lastPos, pos - lastPos)); + lastPos = Str.find_first_not_of(Delimiter, pos); + pos = Str.find_first_of(Delimiter.c_str(), lastPos); + } + + return StrTokens.size(); +} + +inline std::string generateFilePath(std::string Path, std::string Filename) +{ + std::string str = Path; + if (str.at(str.size() - 1) == '\\' || str.at(str.size() - 1) == '/') + { + str += Filename; + } + else + { +#if defined(TARGET_WINDOWS) + str += '\\' + Filename; +#else + str += '/' + Filename; +#endif + } + + return str; +} diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..ee6b138 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,79 @@ +# AppVeyor build script for Kodi's binary add-ons +# +# HOW TO USE +# ----------------- +# 1. Add this file to your binary add-on repository +# 2. Set "addon_id" to your binary add-on id (see below) +# 3. Login at https://ci.appveyor.com (you can use your Github, BitBucket or Visual Studio Online account if you want) +# 4. Go to "PROEJCTS" and add your repository with the "NEW PROJECT" button +# 5. Commit this file to your repository and the build will start +# +# Optional: Adding build badges (build status image) +# 1. Go to "PROJECTS" --> "YOUR-REPOSITORY" --> SETTINGS --> Badges +# 2. Copy the "Sample markdown code" and add it to your README.md +# +# +# TODO: +# - Add support for creating add-on packaging on Git tag pushes +# - Add package uploads to bintray for deployment +# - Add support for a .msi add-on package install file +# - Currently the debug version fails to build. So a fix in Kodi's binary add-on build system is needed +# Afterwards uncomment the matrix debug build +# - Does {shallow_clone}=true improve the fetch perfomance? +# - Fix Kodi's binary add-on build system to enable +# - Is msbuild faster then nmake? + + +version: BuildNr.{build} + +environment: + # DEFINE THE ADD-ON ID HERE + addon_id: adsp.template + + matrix: + # currently the debug version fail, because it doesn't find the .pdb file. + # Seems to be an error in Kodi binary add-on build system + #- GENERATOR: "Visual Studio 12 2013" + #CONFIG: Debug + + - GENERATOR: "Visual Studio 12 2013" + CONFIG: Release + +init: +# Configure the AppVeyor build version to ${branch-name}-${git-revision}-${timestamp} +- ps: $commit = $env:appveyor_repo_commit.SubString(0,7) +- ps: $timestamp = $env:appveyor_repo_commit_timestamp.SubString(0,10) +- ps: Update-AppveyorBuild -Version ("{0}-{1}-{2}" -f $env:appveyor_repo_branch, $commit, $timestamp) + +# uncomment this to build only on specific branches +#branches: + #only: +# - master + +# fetch repository as zip archive +shallow_clone: true # default is "false" + +# example about how to install a newer cmake version +#install: +# - ps: wget https://s3.amazonaws.com/biibinaries/thirdparty/cmake-3.0.2-win32-x86.zip -OutFile cmake.zip +# - cmd: echo "Unzipping cmake..." +# - cmd: 7z x cmake.zip -o"C:\Program Files (x86)\" -y > nul +# - cmd: set PATH=%PATH:CMake 2.8\bin=%;C:\Program Files (x86)\cmake-3.0.2-win32-x86\bin +# - cmd: cmake --version +# - cmd: del cmake.zip + +build_script: + - call "%VS120COMNTOOLS%..\..\VC\bin\vcvars32.bat" + - cd .. + - ren "%APPVEYOR_BUILD_FOLDER%" "%addon_id%" + - mkdir package + - git clone --depth=1 https://github.com/xbmc/xbmc.git + - cd "%addon_id%" + - mkdir build + - cd build + - cmake -G "NMake Makefiles" -DADDONS_TO_BUILD="%addon_id%" -DCMAKE_BUILD_TYPE="%CONFIG%" -DADDON_SRC_PREFIX="../.." -DCMAKE_INSTALL_PREFIX="../../xbmc/addons" -DPACKAGE_ZIP=1 "../../xbmc/project/cmake/addons" + - cmake --build "%cd%" --target "%addon_id%" + + # use this commands for zip package creation, which can be used to upload it + #- cmake -G "NMake Makefiles" -DADDONS_TO_BUILD="%addon_id%" -DCMAKE_BUILD_TYPE="%CONFIG%" -DADDON_SRC_PREFIX="../.." -DCMAKE_INSTALL_PREFIX="../../xbmc/addons" -DPACKAGE_ZIP=1 -DPACKAGE_DIR="C:/projects/package" "../../xbmc/project/cmake/addons" + #- cmake --build "%cd%" --target "package-%addon_id%" diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..c24a2de --- /dev/null +++ b/debian/changelog @@ -0,0 +1,7 @@ +kodi-audiodsp-template (1.0.0-1~trusty) trusty; urgency=low + + [ wsnipex ] + * initial release + + -- wsnipex Sat, 17 May 2014 11:40:22 +0100 + diff --git a/debian/changelog.in b/debian/changelog.in new file mode 100644 index 0000000..1a97300 --- /dev/null +++ b/debian/changelog.in @@ -0,0 +1,7 @@ +kodi-audiodsp-template (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low + + [ kodi ] + * autogenerated dummy changelog + + -- wsnipex Sat, 17 May 2014 11:40:22 +0100 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +8 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..6079182 --- /dev/null +++ b/debian/control @@ -0,0 +1,22 @@ +Source: kodi-audiodsp-template +Priority: extra +Maintainer: wsnipex +Build-Depends: debhelper (>= 8.0.0), cmake, kodi-addon-dev, libkodiplatform-dev, kodi-audio-dev, libfftw3-dev, libsamplerate0-dev, doxygen +Standards-Version: 3.9.2 +Section: libs +Homepage: http://kodi.tv + +Package: kodi-audiodsp-template +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Audio DSP template for KODI + This contains a template for audio DSP addons + +Package: kodi-audiodsp-template-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: debug symbols for Audio DSP template for KODI + contains the debug symbols for xbmc-audiodsp-template + diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..afd55d8 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,43 @@ +Format: http://dep.debian.net/deps/dep5 +Upstream-Name: adsp.template + +Files: * +Copyright: Alwin Esch +License: GPL-2+ + This package 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 of the License, or + (at your option) any later version. + . + This package 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 this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + + +Files: debian/* +Copyright: 2013 Arne Morten Kvarving + 2013 wsnipex +License: GPL-2+ + This package 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 of the License, or + (at your option) any later version. + . + This package 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 this program. If not, see + . + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..602a701 --- /dev/null +++ b/debian/rules @@ -0,0 +1,26 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ + +override_dh_auto_configure: + dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1 + +override_dh_strip: + dh_strip --dbg-package=kodi-audiodsp-template-dbg + +override_dh_auto_install: + dh_auto_install --destdir=debian/kodi-audiodsp-template + +override_dh_installdocs: + dh_installdocs --link-doc=kodi-audiodsp-template + diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/doxygen_resources/Doxyfile.doxy b/doxygen_resources/Doxyfile.doxy new file mode 100644 index 0000000..2da5748 --- /dev/null +++ b/doxygen_resources/Doxyfile.doxy @@ -0,0 +1,2383 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "KODI ADSP Addon Handling" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 0.1.5 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = YES + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = NO + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = NO + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../src \ + ../../../kodi/kodi_adsp_types.h \ + ../../../kodi/kodi_adsp_dll.h \ + ../../../kodi/libKODI_adsp.h + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.as \ + *.js + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = DVDDemuxPacket.h + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = NO + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /