SET(CAPI_LIB "dali-adaptor-internal")
SET(TC_SOURCES
+ utc-Dali-AddOns.cpp
utc-Dali-CommandLineOptions.cpp
utc-Dali-CompressedTextures.cpp
utc-Dali-FontClient.cpp
utc-Dali-TiltSensor.cpp
)
+
LIST(APPEND TC_SOURCES
image-loaders.cpp
../dali-adaptor/dali-test-suite-utils/mesh-builder.cpp
# But CMake's new auto-escape quote policy doesn't work right.
CMAKE_POLICY(SET CMP0005 OLD)
ADD_DEFINITIONS(-DTEST_IMAGE_DIR=\"\\\"${CMAKE_CURRENT_SOURCE_DIR}/../../images\\\"\" )
+ADD_DEFINITIONS(-DADDON_LIBS_PATH=\"\\\"${CMAKE_CURRENT_BINARY_DIR}\\\"\" )
FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
INSTALL(PROGRAMS ${EXEC_NAME}
DESTINATION ${BIN_DIR}/${EXEC_NAME}
)
+
+# build addons
+MESSAGE( STATUS "BINDIR: ${CMAKE_CURRENT_BINARY_DIR}")
+SET(ADDON_NAME SampleAddOn )
+SET(ADDON_SOURCES addons/test-sample-addon.cpp )
+ADD_LIBRARY( ${ADDON_NAME} SHARED ${ADDON_SOURCES} )
+TARGET_LINK_LIBRARIES(${ADDON_NAME}
+ -lpthread -ldl --coverage
+ )
+
+INSTALL( TARGETS ${ADDON_NAME} DESTINATION ${BIN_DIR} )
+
+# store AddOn list
+FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/addons.txt lib${ADDON_NAME}.so )
+
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <cstring>
+#include <dali/devel-api/addons/addon-base.h>
+#include <dali-test-suite-utils.h>
+
+namespace
+{
+bool gIsPaused = false;
+}
+
+int StringLen( const char* str )
+{
+ return strlen( str );
+}
+
+int DoSum( int a, int b )
+{
+ return a+b;
+}
+
+bool GetLifecycleStatus()
+{
+ return gIsPaused;
+}
+
+struct AddOnDataInstance
+{
+ int GetValue()
+ {
+ return 42;
+ }
+
+ static int GetValueWithInstance( AddOnDataInstance* instance )
+ {
+ return instance->GetValue();
+ }
+};
+
+AddOnDataInstance* CreateInstance()
+{
+ return new AddOnDataInstance();
+}
+
+class TestDummyAddOn : public Dali::AddOns::AddOnBase
+{
+public:
+
+ void GetAddOnInfo( Dali::AddOnInfo& info ) override
+ {
+ info.type = Dali::AddOnType::GENERIC;
+ info.name = "SampleAddOn";
+ info.version = Dali::DALI_ADDON_VERSION( 1, 0, 0 );
+ info.next = nullptr;
+ tet_printf( "SampleAddOn: GetAddOnInfo() : name = %s\n", info.name.c_str());
+ }
+
+ /**
+ * Dispatch table for global functions
+ * @return
+ */
+ Dali::AddOns::DispatchTable* GetGlobalDispatchTable() override
+ {
+ static Dali::AddOns::DispatchTable dispatchTable{};
+ if( dispatchTable.Empty() )
+ {
+ dispatchTable["DoSum"] = DoSum;
+ dispatchTable["StringLen"] = StringLen;
+ dispatchTable["GetLifecycleStatus"] = GetLifecycleStatus;
+ dispatchTable["CreateInstance"] = CreateInstance;
+
+ }
+ return &dispatchTable;
+ }
+
+ /**
+ * Lifecycle
+ */
+ void OnStart() override
+ {
+ gIsPaused = false;
+ }
+
+ void OnStop() override
+ {
+ gIsPaused = true;
+ }
+
+ void OnPause() override
+ {
+ gIsPaused = true;
+ }
+
+ void OnResume() override
+ {
+ gIsPaused = false;
+ }
+
+ /**
+ * Dispatch table for instance functions
+ * @return
+ */
+ Dali::AddOns::DispatchTable* GetInstanceDispatchTable() override
+ {
+ static Dali::AddOns::DispatchTable dispatchTable{};
+ if( dispatchTable.Empty() )
+ {
+ dispatchTable["InstanceCall"] = AddOnDataInstance::GetValueWithInstance;
+ }
+ return &dispatchTable;
+ }
+};
+
+REGISTER_ADDON_CLASS( TestDummyAddOn );
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <dali/dali.h>
+#include <dali-test-suite-utils.h>
+#include <dali/integration-api/addon-manager.h>
+#include <dali/internal/addons/common/addon-manager-factory.h>
+#include <dali/devel-api/common/addon-binder.h>
+
+std::unique_ptr<Dali::Integration::AddOnManager> CreateAddOnManager()
+{
+ // Set env variables
+ setenv( "DALI_ADDONS_PATH", ADDON_LIBS_PATH, 1 );
+ setenv( "DALI_ADDONS_LIBS", "libSampleAddOn.so", 1);
+
+ return std::unique_ptr<Dali::Integration::AddOnManager>( Dali::Internal::AddOnManagerFactory::CreateAddOnManager() );
+}
+
+struct TestAddOn : public Dali::AddOn::AddOnBinder
+{
+ TestAddOn() : AddOnBinder( "SampleAddOn", 0u )
+ {}
+
+ ADDON_BIND_FUNCTION( GetLifecycleStatus, bool() );
+};
+
+int UtcDaliTestAddOnInterface(void)
+{
+ TestApplication application;
+ // Create AddOnManager using internal factory
+ auto addOnManager = CreateAddOnManager();
+
+ TestAddOn addon;
+
+ DALI_TEST_EQUALS( addon.IsValid(), true, TEST_LOCATION );
+
+ const auto& info = addon.GetAddOnInfo();
+
+ // Test returned addon version and type
+ DALI_TEST_EQUALS( info.version, Dali::DALI_ADDON_VERSION( 1, 0 , 0), TEST_LOCATION );
+ DALI_TEST_EQUALS( info.type, Dali::AddOnType::GENERIC, TEST_LOCATION );
+
+ // Test lifecycle
+ addOnManager->Pause();
+
+ auto result1 = addon.GetLifecycleStatus();
+ DALI_TEST_EQUALS( result1, true, TEST_LOCATION );
+
+ addOnManager->Resume();
+ auto result2 = addon.GetLifecycleStatus();
+ DALI_TEST_EQUALS( result2, false, TEST_LOCATION );
+
+ END_TEST;
+}
+
+int UtcDaliTestAddOnManager(void)
+{
+ TestApplication application;
+
+ // Create AddOnManager using internal factory
+ auto addOnManagerUPTR = CreateAddOnManager();
+
+ // Get addon-manager
+ auto* addonManager = Dali::Integration::AddOnManager::Get();
+
+ bool result = addonManager != nullptr;
+
+ DALI_TEST_EQUALS( result, true, TEST_LOCATION );
+
+ auto availableAddons = addonManager->EnumerateAddOns();
+
+ // must be 1 addon available
+ DALI_TEST_EQUALS( availableAddons.size(), 1u, TEST_LOCATION );
+
+ Dali::AddOnInfo info{};
+ addonManager->GetAddOnInfo( availableAddons[0], info );
+
+ // Test returned addon version and type
+ DALI_TEST_EQUALS( info.version, Dali::DALI_ADDON_VERSION( 1, 0 , 0), TEST_LOCATION );
+ DALI_TEST_EQUALS( info.type, Dali::AddOnType::GENERIC, TEST_LOCATION );
+
+ // Get addon handle
+ auto testAddon = addonManager->GetAddOn( availableAddons[0] );
+ result = testAddon != 0;
+ DALI_TEST_EQUALS( result, true, TEST_LOCATION );
+
+ // Get addon global function
+ auto createInstance = addonManager->GetGlobalProc<void*()>( testAddon, "CreateInstance");
+ result = createInstance != nullptr;
+ DALI_TEST_EQUALS( result, true, TEST_LOCATION );
+
+ // Test for false positive (queried function must not be found)
+ auto dummyfunction = addonManager->GetGlobalProc<void*()>( testAddon, "ThisFunctionDoesntExist");
+ result = dummyfunction == nullptr;
+ DALI_TEST_EQUALS( result, true, TEST_LOCATION );
+
+ // Get Instance function and call it, expect answer 42
+ auto instanceFunction = addonManager->GetInstanceProc<uint32_t(void*)>( testAddon, "InstanceCall" );
+ auto* instance = createInstance();
+ auto answer = instanceFunction( instance );
+ DALI_TEST_EQUALS( answer, 42, TEST_LOCATION );
+
+ // Test lifecycle
+ auto GetLifecycleStatus = addonManager->GetGlobalProc<bool()>( testAddon, "GetLifecycleStatus");
+ addonManager->Pause();
+
+ DALI_TEST_EQUALS( GetLifecycleStatus(), true, TEST_LOCATION );
+
+ addonManager->Resume();
+ DALI_TEST_EQUALS( GetLifecycleStatus(), false, TEST_LOCATION );
+
+ END_TEST;
+}
\ No newline at end of file
SET( adaptor_thread_dir ${ADAPTOR_ROOT}/dali/internal/thread )
include( ${ADAPTOR_ROOT}/dali/internal/thread/file.list )
+SET( adaptor_addons_dir ${ADAPTOR_ROOT}/dali/internal/addons )
+include( ${ADAPTOR_ROOT}/dali/internal/addons/file.list )
+
SET( adaptor_vector_animation_dir ${ADAPTOR_ROOT}/dali/internal/vector-animation )
include( ${ADAPTOR_ROOT}/dali/internal/vector-animation/file.list )
${devel_api_text_abstraction_src_files}
${static_libraries_libunibreak_src_files}
${static_libraries_glyphy_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_dummy_src_files}
)
IF( ENABLE_ANDROIDJNI_FRAMEWORK )
${adaptor_window_system_tizen_wayland_src_files}
${adaptor_trace_common_src_files}
${adaptor_thread_common_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_dummy_src_files}
${devel_api_text_abstraction_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
${adaptor_window_system_tizen_wayland_src_files}
${adaptor_trace_common_src_files}
${adaptor_thread_common_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_tizen_src_files}
${devel_api_text_abstraction_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
${adaptor_window_system_tizen_wayland_src_files}
${adaptor_trace_common_src_files}
${adaptor_thread_common_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_tizen_src_files}
${devel_api_text_abstraction_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
${adaptor_trace_common_src_files}
${adaptor_thread_common_src_files}
${devel_api_text_abstraction_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_tizen_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
)
${adaptor_thread_common_src_files}
${adaptor_window_system_ubuntu_x11_src_files}
${devel_api_text_abstraction_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_ubuntu_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
)
${adaptor_window_system_tizen_wayland_src_files}
${adaptor_trace_common_src_files}
${adaptor_thread_common_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_tizen_src_files}
${devel_api_text_abstraction_src_files}
${static_libraries_glyphy_src_files}
${static_libraries_libunibreak_src_files}
${adaptor_input_windows_src_files}
${adaptor_clipboard_windows_src_files}
${adaptor_imaging_windows_src_files}
+ ${adaptor_addons_common_src_files}
+ ${adaptor_addons_dummy_src_files}
)
# Builds the c files as c++
// CLASS HEADER
#include <dali/internal/adaptor/common/adaptor-impl.h>
+#include <dali/internal/addons/common/addon-manager-impl.h>
+#include <dali/internal/addons/common/addon-manager-factory.h>
#include <dali/internal/adaptor/common/adaptor-builder-impl.h>
// EXTERNAL INCLUDES
#include <dali/integration-api/events/touch-event-integ.h>
#include <dali/integration-api/events/wheel-event-integ.h>
#include <dali/integration-api/processor-interface.h>
+#include <dali/integration-api/addon-manager.h>
// INTERNAL INCLUDES
#include <dali/public-api/dali-adaptor-common.h>
EglSyncImplementation& eglSyncImpl = eglGraphics->GetSyncImplementation();
EglContextHelperImplementation& eglContextHelperImpl = eglGraphics->GetContextHelperImplementation();
+ // Create the AddOnManager
+ mAddOnManager.reset( Dali::Internal::AddOnManagerFactory::CreateAddOnManager() );
+
mCore = Integration::Core::New( *this,
*mPlatformAbstraction,
mGLES,
mGraphics->GetStencilBufferRequired(),
mGraphics->GetPartialUpdateRequired() );
+
defaultWindow->SetAdaptor( Get() );
Dali::Integration::SceneHolder defaultSceneHolder( defaultWindow );
{
(*iter)->OnStart();
}
+
+ mAddOnManager->Start();
}
// Dali::Internal::Adaptor::Adaptor::Pause
(*iter)->OnPause();
}
+ // Extensions
+ mAddOnManager->Pause();
+
// Pause all windows event handlers when adaptor paused
for( auto window : mWindows )
{
window->Resume();
}
+ // Resume AddOnManager
+ mAddOnManager->Resume();
+
// Inform observers that we have resumed.
for( ObserverContainer::iterator iter = mObservers.begin(), endIter = mObservers.end(); iter != endIter; ++iter )
{
(*iter)->OnStop();
}
+ mAddOnManager->Stop();
+
mThreadController->Stop();
// Delete the TTS player
class Core;
class GlAbstraction;
class Processor;
+class AddOnManager;
}
namespace Internal
const bool mEnvironmentOptionsOwned:1; ///< Whether we own the EnvironmentOptions (and thus, need to delete it)
bool mUseRemoteSurface:1; ///< whether the remoteSurface is used or not
+ std::unique_ptr<Integration::AddOnManager> mAddOnManager; ///< Pointer to the addon manager
+
public:
inline static Adaptor& GetImplementation(Dali::Adaptor& adaptor) { return *adaptor.mImpl; }
};
# module: adaptor, backend: common
-SET( adaptor_adaptor_common_src_files
- ${adaptor_adaptor_dir}/common/lifecycle-controller-impl.cpp
- ${adaptor_adaptor_dir}/common/adaptor-impl.cpp
- ${adaptor_adaptor_dir}/common/adaptor.cpp
- ${adaptor_adaptor_dir}/common/adaptor-builder-impl.cpp
- ${adaptor_adaptor_dir}/common/application-impl.cpp
- ${adaptor_adaptor_dir}/common/combined-update-render-controller.cpp
+SET( adaptor_adaptor_common_src_files
+ ${adaptor_adaptor_dir}/common/lifecycle-controller-impl.cpp
+ ${adaptor_adaptor_dir}/common/adaptor-impl.cpp
+ ${adaptor_adaptor_dir}/common/adaptor.cpp
+ ${adaptor_adaptor_dir}/common/adaptor-builder-impl.cpp
+ ${adaptor_adaptor_dir}/common/application-impl.cpp
+ ${adaptor_adaptor_dir}/common/combined-update-render-controller.cpp
${adaptor_adaptor_dir}/common/system-cache-path.cpp
)
# module: adaptor, backend: tizen-wayland
-SET( adaptor_adaptor_tizen_wayland_src_files
- ${adaptor_adaptor_dir}/tizen-wayland/adaptor-impl-tizen.cpp
+SET( adaptor_adaptor_tizen_wayland_src_files
+ ${adaptor_adaptor_dir}/tizen-wayland/adaptor-impl-tizen.cpp
${adaptor_adaptor_dir}/tizen-wayland/framework-tizen.cpp
)
# module: adaptor, backend: tizen-wearable
-SET( adaptor_adaptor_tizen_wearable_src_files
- ${adaptor_adaptor_dir}/tizen-wayland/tizen-wearable/watch-application.cpp
+SET( adaptor_adaptor_tizen_wearable_src_files
+ ${adaptor_adaptor_dir}/tizen-wayland/tizen-wearable/watch-application.cpp
${adaptor_adaptor_dir}/tizen-wayland/tizen-wearable/watch-application-impl.cpp
)
# module: adaptor, backend: ubuntu
-SET( adaptor_adaptor_ubuntu_src_files
- ${adaptor_adaptor_dir}/generic/adaptor-impl-generic.cpp
+SET( adaptor_adaptor_ubuntu_src_files
+ ${adaptor_adaptor_dir}/generic/adaptor-impl-generic.cpp
${adaptor_adaptor_dir}/ubuntu/framework-ubuntu.cpp
)
--- /dev/null
+#ifndef DALI_ADDON_MANAGER_FACTORY
+#define DALI_ADDON_MANAGER_FACTORY
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/addon-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+/**
+ * @brief The base AddOnManager factory class
+ */
+class AddOnManagerFactory
+{
+public:
+ /**
+ * @brief Creates AddOnManager
+ * @return returns AddOnManager object or nullptr if no support
+ */
+ static Integration::AddOnManager* CreateAddOnManager();
+};
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_ADDON_MANAGER_FACTORY
\ No newline at end of file
--- /dev/null
+#ifndef DALI_INTERNAL_ADDON_MANAGER_IMPL
+#define DALI_INTERNAL_ADDON_MANAGER_IMPL
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/addon-manager.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace Dali
+{
+namespace Internal
+{
+/**
+ * Base class for platform-specific implementation of AddOnManager
+ */
+class AddOnManager
+{
+protected:
+
+ /**
+ * @brief Constructor
+ */
+ AddOnManager() = default;
+
+public:
+ /**
+ * @brief Destructor
+ */
+ virtual ~AddOnManager() = default;
+
+ /**
+ * @brief Registers the dispatch table with AddOnManager.
+ * @param[in] dispatchTable Pointer to the valid dispatch table
+ */
+ virtual void RegisterAddOnDispatchTable( const AddOnDispatchTable* dispatchTable ) = 0;
+
+ /**
+ * @brief Retrieves list of the available AddOns
+ * @return List of AddOn names
+ */
+ virtual std::vector<std::string> EnumerateAddOns() = 0;
+
+ /**
+ * @brief Returns AddOnInfo structure for specified AddOn name
+ * @param[in] name Name of AddOn
+ * @param[out]] info Output reference
+ * @return True on success, False if extension info cannot be retrieved
+ */
+ virtual bool GetAddOnInfo(const std::string& name, AddOnInfo& info ) = 0;
+
+ /**
+ * @brief Loads and initialises specified AddOns
+ * @param[in] extensionNames Array of extension names
+ * @return vector of initialised AddOnLibrary handles
+ */
+ virtual std::vector<Dali::AddOnLibrary> LoadAddOns( const std::vector<std::string>& addonNames ) = 0;
+
+ /**
+ * @brief Returns AddOn global function pointer
+ * @param[in] addOnLibrary valid AddOn library object
+ * @param[in] procName Name of the function to retrieve
+ * @return Pointer to the function or null if function doesn't exist
+ */
+ virtual void* GetGlobalProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) = 0;
+
+ /**
+ * @brief Returns addon instance function pointer
+ * @param[in] addOnLibrary valid AddOn library object
+ * @param[in] procName Name of the function to retrieve
+ * @return Pointer to the function or null if function doesn't exist
+ */
+ virtual void* GetInstanceProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) = 0;
+
+ /**
+ * @brief Pause lifecycle event
+ * Implementation is optional and depends whether AddOn needs to handle lifecycle event.
+ */
+ virtual void Pause() {}
+
+ /**
+ * @brief Resume lifecycle event
+ * Implementation is optional and depends whether AddOn needs to handle lifecycle event.
+ */
+ virtual void Resume() {}
+
+ /**
+ * @brief Start lifecycle event
+ * Implementation is optional and depends whether AddOn needs to handle lifecycle event.
+ */
+ virtual void Start() {}
+
+ /**
+ * @brief Stop lifecycle event
+ * Implementation is optional and depends whether AddOn needs to handle lifecycle event.
+ */
+ virtual void Stop() {}
+};
+
+} // Internal
+
+} // Dali
+
+#endif // DALI_CMAKE_EXTENSION_MANAGER_IMPL
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include "addon-manager.h"
+#include <dali/internal/addons/common/addon-manager-impl.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace AddOnManagerFactory
+{
+__attribute__((weak)) Dali::Integration::AddOnManager* CreateAddOnManager()
+{
+ return nullptr;
+}
+
+} // AddOnManagerFactory
+}
+
+namespace Adaptor
+{
+
+AddOnManager::AddOnManager(Internal::AddOnManager* impl ) : Integration::AddOnManager()
+{
+ mImpl.reset(impl);
+}
+
+AddOnManager::~AddOnManager() = default;
+
+void AddOnManager::RegisterAddOnDispatchTable( const AddOnDispatchTable* dispatchTable )
+{
+ mImpl->RegisterAddOnDispatchTable( dispatchTable );
+}
+
+std::vector<std::string> AddOnManager::EnumerateAddOns()
+{
+ return mImpl->EnumerateAddOns();
+}
+
+bool AddOnManager::GetAddOnInfo(const std::string& name, AddOnInfo& info )
+{
+ return mImpl->GetAddOnInfo( name, info );
+}
+
+std::vector<Dali::AddOnLibrary> AddOnManager::LoadAddOns(const std::vector<std::string>& addonNames )
+{
+ return std::move(mImpl->LoadAddOns( addonNames ));
+}
+
+void* AddOnManager::GetGlobalProc(const Dali::AddOnLibrary& addonHandle, const char *procName)
+{
+ return mImpl->GetGlobalProc( addonHandle, procName );
+}
+
+void* AddOnManager::GetInstanceProc(const Dali::AddOnLibrary& addonHandle, const char* procName )
+{
+ return mImpl->GetInstanceProc( addonHandle, procName );
+}
+
+void AddOnManager::Pause()
+{
+ mImpl->Pause();
+}
+
+void AddOnManager::Resume()
+{
+ mImpl->Resume();
+}
+
+void AddOnManager::Start()
+{
+ mImpl->Start();
+}
+
+void AddOnManager::Stop()
+{
+ mImpl->Stop();
+}
+
+}
+}
\ No newline at end of file
--- /dev/null
+#ifndef DALI_ADAPTOR_COMMON_ADDON_MANAGER
+#define DALI_ADAPTOR_COMMON_ADDON_MANAGER
+
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/addon-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class AddOnManager;
+};
+
+namespace Adaptor
+{
+
+class AddOnManager : public Dali::Integration::AddOnManager
+{
+public:
+
+ /**
+ * @brief Constructor
+ * @param impl Pointer to the platform specific implementation
+ */
+ explicit AddOnManager(Internal::AddOnManager* impl);
+
+ /**
+ * @brief Destructor
+ */
+ ~AddOnManager() override;
+
+ /**
+ * @brief Registers a dispatch table for new AddOn. Dispatch table contains essential
+ * functions that will be called by the AddOnManager. It also includes lifecycle
+ * event callbacks.
+ * @param[in] dispatchTable Valid pointer to the DispatchTable object
+ */
+ void RegisterAddOnDispatchTable( const AddOnDispatchTable* dispatchTable ) override;
+
+ /**
+ * @brief Retrieves list of all the extensions available
+ * @return List of AddOn names
+ */
+ std::vector<std::string> EnumerateAddOns() override;
+
+ /**
+ * @brief Returns AddOnInfo structure for specified extension name
+ * @param[in] name Name of extension
+ * @param[out]] info Output reference
+ * @return True on success, False if extension info cannot be retrieved
+ */
+ bool GetAddOnInfo(const std::string& name, AddOnInfo& info ) override;
+
+ /**
+ * @brief Loads and initialises specified extensions
+ *
+ * @param[in] extensionNames Array of extension names
+ * @return vector of initialised extension handles
+ */
+ std::vector<AddOnLibrary> LoadAddOns( const std::vector<std::string>& addonNames ) override;
+
+ /**
+ * @brief Returns addon global function pointer
+ * @param[in] addonHandle Addon handle
+ * @param[in] procName Name of the function to retrieve
+ * @return Pointer to the function or null if function doesn't exist
+ */
+ void* GetGlobalProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) override;
+
+ /**
+ * @brief Returns addon instance function pointer
+ * @param[in] addonHandle Addon handle
+ * @param[in] procName Name of the function to retrieve
+ * @return Pointer to the function or null if function doesn't exist
+ */
+ void* GetInstanceProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) override;
+
+ /**
+ * @brief Lifecycle pause function
+ */
+ void Pause() override;
+
+ /**
+ * @brief Lifecycle resume function
+ */
+ void Resume() override;
+
+ /**
+ * @brief Lifecycle start function
+ */
+ void Start() override;
+
+ /**
+ * @brief Lifecycle stop function
+ */
+ void Stop() override;
+
+private:
+
+ std::unique_ptr<Internal::AddOnManager> mImpl; /// Implementation of the AddOnManager
+
+};
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_ADAPTOR_COMMON_ADDON_MANAGER
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/addons/common/addon-manager-factory.h>
+
+namespace Dali
+{
+namespace Internal
+{
+Integration::AddOnManager* AddOnManagerFactory::CreateAddOnManager()
+{
+ // AddOnManager may be not implemented.
+ return nullptr;
+}
+
+} // namespace Internal
+} // namespace Dali
--- /dev/null
+
+# module: addons, backend: common
+SET( adaptor_addons_common_src_files
+ ${adaptor_addons_dir}/common/addon-manager.cpp
+)
+
+# module: addons, backend: tizen
+SET( adaptor_addons_tizen_src_files
+ ${adaptor_addons_dir}/linux/addon-manager-impl-linux.cpp
+ ${adaptor_addons_dir}/tizen/addon-manager-factory-tizen.cpp
+)
+
+# module: addons, backend: ubuntu
+SET( adaptor_addons_ubuntu_src_files
+ ${adaptor_addons_dir}/linux/addon-manager-impl-linux.cpp
+ ${adaptor_addons_dir}/ubuntu/addon-manager-factory-ubuntu.cpp
+)
+
+# module: addons, backend: dummy
+SET( adaptor_addons_dummy_src_files
+ ${adaptor_addons_dir}/dummy/addon-manager-factory-dummy.cpp
+)
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/addons/linux/addon-manager-impl-linux.h>
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/internal/system/common/environment-variables.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+#include <dlfcn.h>
+#include <functional>
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+
+namespace Dali
+{
+namespace Internal
+{
+
+AddOnManagerLinux::AddOnManagerLinux() = default;
+
+AddOnManagerLinux::~AddOnManagerLinux() = default;
+
+void AddOnManagerLinux::RegisterAddOnDispatchTable( const AddOnDispatchTable* dispatchTable )
+{
+ mAddOnNames.emplace_back(dispatchTable->name);
+ mAddOnCache.emplace_back();
+ mAddOnCache.back().GetGlobalProc = dispatchTable->GetGlobalProc;
+ mAddOnCache.back().GetInstanceProc = dispatchTable->GetInstanceProc;
+ mAddOnCache.back().GetAddOnInfo = dispatchTable->GetAddOnInfo;
+
+ auto& callbacks = mAddOnCache.back().lifecycleCallbacks;
+ auto initEvent = [&callbacks](uint32_t event, void(*fn)() ) {
+ callbacks[event].function = fn;
+ callbacks[event].initialized = true;
+ };
+
+ initEvent( LifecycleCallback::EVENT_START, dispatchTable->OnStart );
+ initEvent( LifecycleCallback::EVENT_STOP, dispatchTable->OnStop );
+ initEvent( LifecycleCallback::EVENT_PAUSE, dispatchTable->OnPause );
+ initEvent( LifecycleCallback::EVENT_RESUME, dispatchTable->OnResume );
+}
+
+std::vector<std::string> AddOnManagerLinux::EnumerateAddOns()
+{
+ if( mAddOnNames.empty() )
+ {
+ // AddOn libs must be separated with ':' character
+ const char *addonsLibs = Dali::EnvironmentVariable::GetEnvironmentVariable( DALI_ENV_ADDONS_LIBS );
+ if (!addonsLibs)
+ {
+ return {};
+ }
+
+ // Get the path where addon libs are stored
+ const char *addonsPath = Dali::EnvironmentVariable::GetEnvironmentVariable( DALI_ENV_ADDONS_PATH );
+ std::string addonsPathStr(addonsPath ? addonsPath : "/usr/lib");
+
+ // Split libs
+ std::string addonLibsStr(addonsLibs);
+ std::vector<std::string> results;
+ results.emplace_back();
+
+ std::find_if(addonLibsStr.begin(), addonLibsStr.end(), [&results](char &c)
+ {
+ if (c == ':')
+ {
+ results.emplace_back();
+ }
+ else
+ {
+ results.back() += c;
+ }
+ return false;
+ });
+
+ const char *EXTENSION_PATH = (addonsPath) ? addonsPath : "/usr/lib";
+
+ for (auto &name : results)
+ {
+ std::string fullPath(EXTENSION_PATH);
+ fullPath += "/";
+ fullPath += name;
+
+ // open lib, look for essential symbols. The libary is opened with RTLD_DEEPBIND flag
+ // to make sure the local symbol table is going to be used during lookup first.
+ auto* handle = dlopen(fullPath.c_str(), RTLD_DEEPBIND|RTLD_LAZY);
+ if (handle)
+ {
+ auto& cacheEntry = mAddOnCache.back();
+ AddOnInfo info{};
+ cacheEntry.GetAddOnInfo(info);
+ cacheEntry.info = info;
+ cacheEntry.addOnLib = fullPath;
+ cacheEntry.libHandle = handle;
+ cacheEntry.opened = false;
+ }
+ else
+ {
+ DALI_LOG_ERROR("Can't open library: %s, error: %s\n", fullPath.c_str(), dlerror());
+ }
+ }
+ }
+ return mAddOnNames;
+}
+
+bool AddOnManagerLinux::GetAddOnInfo(const std::string& name, AddOnInfo& info )
+{
+ if( mAddOnNames.empty() )
+ {
+ EnumerateAddOns();
+ }
+
+ if( mAddOnNames.empty() )
+ {
+ return false;
+ }
+
+ auto iter = std::find_if( mAddOnCache.begin(), mAddOnCache.end(), [name]( AddOnCacheEntry& item )
+ {
+ return (item.info.name == name);
+ });
+
+ if (iter == mAddOnCache.end())
+ {
+ return false;
+ }
+
+ info = iter->info;
+ return true;
+}
+
+std::vector<Dali::AddOnLibrary> AddOnManagerLinux::LoadAddOns( const std::vector<std::string>& addonNames )
+{
+ std::vector<AddOnLibrary> retval{};
+ retval.resize( addonNames.size() );
+ std::fill( retval.begin(), retval.end(), nullptr );
+
+ if( mAddOnCache.empty() )
+ {
+ EnumerateAddOns();
+ if(mAddOnCache.empty())
+ {
+ // no any extensions
+ return retval;
+ }
+ }
+
+ auto nameIndex = 0u;
+ for( const auto& name : addonNames )
+ {
+ auto index = 0u;
+ nameIndex++;
+ auto iter = std::find_if( mAddOnCache.begin(), mAddOnCache.end(), [&index, name]( AddOnCacheEntry& item )
+ {
+ ++index;
+ return (item.info.name == name);
+ });
+
+ if(iter == mAddOnCache.end())
+ {
+ continue;
+ }
+
+ if(!iter->opened && iter->libHandle)
+ {
+ // Open library, pull symbols and keep the handle
+ auto& entry = *iter;
+ entry.opened = true;
+ }
+
+ // Store cache index of extension for indirect calling
+ // Stored number in this implementation is always +1 (0 is nullptr, unsuccessful)
+ retval[nameIndex-1] = reinterpret_cast<void*>( index );
+ }
+
+ return retval;
+}
+
+void* AddOnManagerLinux::GetGlobalProc( const Dali::AddOnLibrary& addonHandle, const char* procName )
+{
+ if( !addonHandle )
+ {
+ return nullptr;
+ }
+
+ auto index = (intptr_t(addonHandle));
+ const auto& entry = mAddOnCache[ index-1 ];
+
+ if(entry.opened && entry.libHandle )
+ {
+ // First call into dispatch table
+ auto retval = entry.GetGlobalProc( procName );
+ if( !retval )
+ {
+ // fallback
+ retval = dlsym( entry.libHandle, procName );
+ }
+ return retval;
+ }
+ else
+ {
+ DALI_LOG_ERROR("AddOn: GetGlobalProc() library failed!\n");
+ }
+ return nullptr;
+}
+
+void* AddOnManagerLinux::GetInstanceProc( const Dali::AddOnLibrary& addonHandle, const char* procName )
+{
+ if( !addonHandle )
+ {
+ return nullptr;
+ }
+
+ auto index = (intptr_t(addonHandle));
+ const auto& entry = mAddOnCache[ index-1 ];
+ if(entry.opened && entry.libHandle )
+ {
+ // First call into dispatch table
+ auto retval = entry.GetInstanceProc( procName );
+ if( !retval )
+ {
+ // fallback
+ retval = dlsym( entry.libHandle, procName );
+ }
+ return retval;
+ }
+ return nullptr;
+}
+
+void AddOnManagerLinux::Pause()
+{
+ InvokeLifecycleFunction( LifecycleCallback::EVENT_PAUSE );
+}
+
+void AddOnManagerLinux::Resume()
+{
+ InvokeLifecycleFunction( LifecycleCallback::EVENT_RESUME );
+}
+
+void AddOnManagerLinux::Start()
+{
+ InvokeLifecycleFunction( LifecycleCallback::EVENT_START );
+}
+
+void AddOnManagerLinux::Stop()
+{
+ InvokeLifecycleFunction( LifecycleCallback::EVENT_STOP );
+}
+
+void AddOnManagerLinux::InvokeLifecycleFunction( uint32_t lifecycleEvent )
+{
+ for( auto& entry : mAddOnCache )
+ {
+ auto& callback = entry.lifecycleCallbacks[lifecycleEvent];
+
+ // If AddOn didn't auto-register try to pull symbols
+ // directly out of the addon
+ if(!callback.initialized)
+ {
+ callback.function = reinterpret_cast<decltype(callback.function)>(entry.GetGlobalProc(callback.functionName.c_str()));
+ callback.initialized = true;
+ }
+ if(callback.function)
+ {
+ callback.function();
+ }
+ }
+}
+
+} // namespace Internal
+} // namespace Dali
\ No newline at end of file
--- /dev/null
+#ifndef DALI_ADDON_MANAGER_IMPL_LINUX
+#define DALI_ADDON_MANAGER_IMPL_LINUX
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/addons/common/addon-manager-impl.h>
+#include <dali/internal/addons/common/addon-manager.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+#include <string>
+#include <memory>
+
+namespace Dali
+{
+namespace Internal
+{
+
+/**
+ * Implementation of AddOnManager for Linux based platforms (ie. Tizen, Ubuntu)
+ */
+class AddOnManagerLinux : public Internal::AddOnManager
+{
+public:
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager()
+ */
+ AddOnManagerLinux();
+
+ /**
+ * @copydoc Dali::Internal::~AddOnManager()
+ */
+ ~AddOnManagerLinux() override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::RegisterAddOnDispatchTable()
+ */
+ void RegisterAddOnDispatchTable( const AddOnDispatchTable* dispatchTable ) override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::EnumerateAddOns()
+ */
+ std::vector<std::string> EnumerateAddOns() override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::GetAddOnInfo()
+ */
+ bool GetAddOnInfo(const std::string& name, AddOnInfo& info ) override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::LoadAddOns()
+ */
+ std::vector<Dali::AddOnLibrary> LoadAddOns( const std::vector<std::string>& extensionNames ) override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::GetGlobalProc()
+ */
+ void* GetGlobalProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::GetInstanceProc()
+ */
+ void* GetInstanceProc( const Dali::AddOnLibrary& addonHandle, const char* procName ) override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::Pause()
+ */
+ void Pause() override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::Resume()
+ */
+ void Resume() override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::Start()
+ */
+ void Start() override;
+
+ /**
+ * @copydoc Dali::Internal::AddOnManager::Stop()
+ */
+ void Stop() override;
+
+private:
+
+ /**
+ * @brief Invokes lifecycle event handling function based on incoming event
+ * @param[in] lifecycleEvent The lifecycle event
+ */
+ void InvokeLifecycleFunction( uint32_t lifecycleEvent );
+
+ /**
+ * @struct Lifecycle callback structure
+ * The instance of the LifecycleCallback handles a single lifecycle
+ * event and is bound to an AddOn lifecycle function. The lifecycle
+ * function is optional and in case it doesn't exist, the event
+ * will be ignored.
+ */
+ struct LifecycleCallback
+ {
+ const static uint32_t EVENT_PAUSE = 0u; ///< pause event
+ const static uint32_t EVENT_RESUME = 1u; ///< resume event
+ const static uint32_t EVENT_START = 2u; ///< start event
+ const static uint32_t EVENT_STOP = 3u; ///< stop event
+
+ /**
+ * @brief Constructor
+ * @param[in] funcName name of the lifecycle function
+ */
+ explicit LifecycleCallback(const char* funcName)
+ {
+ functionName = funcName;
+ }
+
+ std::string functionName; ///< Name of lifecycle function
+ void(*function)() = nullptr; ///< Lifecycle function pointer
+ bool initialized { false }; ///< Flag indicates whether LifecycleCallback is initialized
+ };
+
+ /**
+ * @struct AddOnCacheEntry
+ * @brief Instance of AddOnCacheEntry stores AddOn essential
+ * function pointers and library handle.
+ */
+ struct AddOnCacheEntry
+ {
+ std::string addOnLib{};
+ AddOnInfo info{};
+
+ // library handle
+ void* libHandle {nullptr};
+
+ // main function pointers
+ void(*GetAddOnInfo)(AddOnInfo& ) = nullptr; ///< Returns AddOnInfo structure
+ void*(*GetInstanceProc)( const char* ) = nullptr; ///< Returns pointer of instance function (member funtion)
+ void*(*GetGlobalProc)( const char* ) = nullptr; ///< Returns pointer of global function (non-member function)
+
+ // lifecycle functions
+ std::vector<LifecycleCallback> lifecycleCallbacks =
+ {
+ LifecycleCallback{ "OnPause" },
+ LifecycleCallback{ "OnResume" },
+ LifecycleCallback{ "OnStart" },
+ LifecycleCallback{ "OnStop" },
+ };
+ bool opened{false};
+ };
+
+ std::vector<AddOnCacheEntry> mAddOnCache;
+ std::vector<std::string> mAddOnNames;
+};
+
+
+}
+}
+#endif //DALI_CMAKE_EXTENSION_MANAGER_IMPL_UBUNTU
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/addons/common/addon-manager-factory.h>
+#include <dali/internal/addons/linux/addon-manager-impl-linux.h>
+
+namespace Dali
+{
+namespace Internal
+{
+Integration::AddOnManager* AddOnManagerFactory::CreateAddOnManager()
+{
+ return new Dali::Adaptor::AddOnManager( new AddOnManagerLinux() );
+}
+
+} // namespace Internal
+} // namespace Dali
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/addons/common/addon-manager-factory.h>
+#include <dali/internal/addons/linux/addon-manager-impl-linux.h>
+
+namespace Dali
+{
+namespace Internal
+{
+Integration::AddOnManager* AddOnManagerFactory::CreateAddOnManager()
+{
+ return new Dali::Adaptor::AddOnManager( new AddOnManagerLinux() );
+}
+
+} // namespace Internal
+} // namespace Dali
#define DALI_ENV_DPI_VERTICAL "DALI_DPI_VERTICAL"
+#define DALI_ENV_ADDONS_PATH "DALI_ADDONS_PATH"
+
+#define DALI_ENV_ADDONS_LIBS "DALI_ADDONS_LIBS"
+
} // namespace Adaptor
} // namespace Internal