diff --git a/Makefile.am b/Makefile.am index a59ef62..ec8267b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,4 +4,5 @@ AM_CPPFLAGS+= -I"$(top_srcdir)/hcore/include" bin_PROGRAMS = harikoff harikoff_SOURCES = main.cpp -harikoff_LDADD = hcore/libhcore.a hcore/deviceManager/libdeviceManager.a +harikoff_LDADD = hcore/libhcore.a hcore/deviceManager/libdeviceManager.a \ + hcore/senseApis/libsenseApis.a diff --git a/configure.ac b/configure.ac index a11f072..a980b1a 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,10 @@ AS_IF([test -z "${LEX}" || test -z "${YACC}"], [ AC_MSG_ERROR([LEX and YACC must both be available in PATH.]) ]) +AC_SEARCH_LIBS([dlopen], [dl ldl], [], [ + AC_MSG_ERROR([dlopen() not found in libdl or libldl.]) +]) + AM_CPPFLAGS=m4_normalize(["-I\"\$(top_srcdir)/include\""]) AC_SUBST([AM_CPPFLAGS]) @@ -53,6 +57,7 @@ AC_CONFIG_HEADERS([include/config.h]) AC_CONFIG_FILES([ Makefile hcore/Makefile hcore/deviceManager/Makefile + hcore/senseApis/Makefile ]) AC_CONFIG_COMMANDS_POST([ diff --git a/hcore/Makefile.am b/hcore/Makefile.am index d87b30c..8c63061 100644 --- a/hcore/Makefile.am +++ b/hcore/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = deviceManager +SUBDIRS = deviceManager senseApis AM_CPPFLAGS+= -I"$(top_srcdir)/hcore/include" noinst_LIBRARIES = libhcore.a diff --git a/hcore/include/senseApis/senseApiManager.h b/hcore/include/senseApis/senseApiManager.h new file mode 100644 index 0000000..304947a --- /dev/null +++ b/hcore/include/senseApis/senseApiManager.h @@ -0,0 +1,69 @@ +#ifndef SENSE_API_MANAGER_H +#define SENSE_API_MANAGER_H + +#include +#include +#include +#include +#include +#include + +struct SenseApiInstance { + int a; + + bool operator==(const SenseApiInstance& other) const { + return a == other.a; + } +}; + +class SenseApiLib { +public: + std::string libraryPath; + std::unique_ptr handle; + + SenseApiLib(const std::string& path) + : libraryPath(path), handle(nullptr, &dlclose) {} +}; + +class SenseApiManager { +public: + static SenseApiManager& getInstance() + { + static SenseApiManager instance + { +#ifdef CONFIG_SENSEAPI_FOO + "builtinApi1", +#endif +#ifdef CONFIG_SENSEAPI_BAR + "builtinApi2", +#endif + // X11 XCB is always built-in. + "x11-xcb" + }; + + return instance; + } + + void registerSenseApi(const SenseApiInstance& apiInstance); + void unregisterSenseApi(const SenseApiInstance& apiInstance); + + SenseApiLib& loadSenseApiLib(const std::string& libraryPath); + std::optional> getSenseApiLib( + const std::string& libraryPath); + void unloadSenseApiLib(const std::string& libraryPath); + +private: + SenseApiManager() = delete; + SenseApiManager(std::initializer_list builtinApis) + : builtinSenseApis(builtinApis) {} + ~SenseApiManager() = default; + + SenseApiManager(const SenseApiManager&) = delete; + SenseApiManager& operator=(const SenseApiManager&) = delete; + + std::vector> senseApiInstances; + std::vector> senseApiLibs; + const std::vector builtinSenseApis; +}; + +#endif // SENSE_API_MANAGER_H diff --git a/hcore/include/senseApis/x11-xcb.h b/hcore/include/senseApis/x11-xcb.h new file mode 100644 index 0000000..5bb80c7 --- /dev/null +++ b/hcore/include/senseApis/x11-xcb.h @@ -0,0 +1,24 @@ +#ifndef X11_XCB_API_H +#define X11_XCB_API_H + +#include +#include +#include + +class X11XcbApi +{ +public: + X11XcbApi(const std::string& displayName); + ~X11XcbApi(); + + void addDevice(const std::string& deviceSpec); + void removeDevice(const std::string& deviceSpec); + void addAllDevicesFromSpecs(const std::vector& deviceSpecs); + +private: + std::string displayName; + std::vector> deviceSpecs; + // Add other necessary members and methods +}; + +#endif // X11_XCB_API_H diff --git a/hcore/senseApis/Makefile.am b/hcore/senseApis/Makefile.am new file mode 100644 index 0000000..b7772f2 --- /dev/null +++ b/hcore/senseApis/Makefile.am @@ -0,0 +1,6 @@ +AM_CPPFLAGS+= -I"$(top_srcdir)/hcore/include" + +noinst_LIBRARIES=libsenseApis.a +libsenseApis_a_SOURCES=senseApiManager.cpp + +senseApiManager.o: AM_CPPFLAGS+=-Wno-ignored-attributes diff --git a/hcore/senseApis/senseApiManager.cpp b/hcore/senseApis/senseApiManager.cpp new file mode 100644 index 0000000..7204f38 --- /dev/null +++ b/hcore/senseApis/senseApiManager.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include + +std::vector> senseApiLibs; +std::vector> senseApiInstances; + +SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath) +{ + auto lib = std::make_unique(libraryPath); + + // Clear any existing error + dlerror(); + lib->handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY)); + if (!lib->handle) + { + std::string error = dlerror() + ? dlerror() + : "Unknown error while opening shlib"; + throw std::runtime_error( + std::string(__func__) + " - Cannot load library '" + + libraryPath + "': " + + error); + } + + senseApiLibs.push_back(std::move(lib)); + return *senseApiLibs.back(); +} + +std::optional> SenseApiManager::getSenseApiLib( + const std::string& libraryPath) +{ + auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(), + [&libPath = libraryPath](const std::unique_ptr& lib) { + return lib->libraryPath == libPath; + } + ); + + if (it != senseApiLibs.end()) { return **it; } + return std::nullopt; +} + +void SenseApiManager::unloadSenseApiLib(const std::string& libraryPath) +{ + auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(), + [&lpath = libraryPath](const std::unique_ptr& lib) { + return lib->libraryPath == lpath; + } + ); + + if (it != senseApiLibs.end()) + { + senseApiLibs.erase(it); + return; + } + + std::cerr << std::string(__func__) + ": Library not found: " + << libraryPath << '\n'; +} + +void SenseApiManager::registerSenseApi(const SenseApiInstance& apiInstance) +{ + auto it = std::find_if( + senseApiInstances.begin(), senseApiInstances.end(), + [&apiInstance](const std::unique_ptr& instance) { + return static_cast(*instance) == apiInstance; + }); + + if (it != senseApiInstances.end()) + { + std::cerr << std::string(__func__) + + ": Sense API Instance already registered.\n"; + return; + } + + senseApiInstances.push_back(std::make_unique(apiInstance)); +} + +void SenseApiManager::unregisterSenseApi(const SenseApiInstance& apiInstance) +{ + auto it = std::find_if( + senseApiInstances.begin(), senseApiInstances.end(), + [&apiInstance](const std::unique_ptr& instance) { + return const_cast(*instance) == apiInstance; + }); + + if (it != senseApiInstances.end()) { + senseApiInstances.erase(it); + } else { + std::cerr << std::string(__func__) + ": Sense API Instance not found.\n"; + } +} diff --git a/hcore/senseApis/x11-xcb.cpp b/hcore/senseApis/x11-xcb.cpp new file mode 100644 index 0000000..e86cde4 --- /dev/null +++ b/hcore/senseApis/x11-xcb.cpp @@ -0,0 +1,47 @@ +#include +#include + +X11XcbApi::X11XcbApi(const std::string& displayName) + : displayName(displayName) +{ +} + +X11XcbApi::~X11XcbApi() { + // Add any necessary cleanup code +} + +bool X11XcbApi::initialize() { + // Add initialization code + std::cout << "Initializing X11 XCB API with display: " << displayName << std::endl; + return true; +} + +void X11XcbApi::shutdown() { + // Add shutdown code + std::cout << "Shutting down X11 XCB API" << std::endl; +} + +void X11XcbApi::addDevice(const std::string& deviceSpec) { + // Add code to add a device + auto device = std::make_shared(deviceSpec); + deviceSpecs.push_back(device); + std::cout << "Adding device with spec: " << deviceSpec << std::endl; +} + +void X11XcbApi::removeDevice(const std::string& deviceSpec) { + // Add code to remove a device + auto it = std::remove_if(deviceSpecs.begin(), deviceSpecs.end(), + [&deviceSpec](const std::shared_ptr& device) { + return device->spec == deviceSpec; + }); + if (it != deviceSpecs.end()) { + deviceSpecs.erase(it, deviceSpecs.end()); + std::cout << "Removing device with spec: " << deviceSpec << std::endl; + } +} + +void X11XcbApi::addAllDevicesFromSpecs(const std::vector& deviceSpecs) { + for (const auto& spec : deviceSpecs) { + addDevice(spec); + } +}