diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | irmp/irmp-main-sharedlib.c | 112 | ||||
-rw-r--r-- | irmp/irmp-main-sharedlib.h | 44 |
4 files changed, 159 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 9e15c30..32c6dd6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,8 @@ libirmp_la_SOURCES = \ irmp/irmpsystem.h \ irmp/irmpprotocols.h noinst_HEADERS += irmp/irmp.c +libirmp_la_CFLAGS = $(LIBIRMP_CFLAGS) +libirmp_la_LIBADD = $(LIBIRMP_LIBS) libirmp_la_LDFLAGS = -no-undefined -version-info 0:0:0 endif diff --git a/configure.ac b/configure.ac index c1314bb..7a2795f 100644 --- a/configure.ac +++ b/configure.ac @@ -159,6 +159,7 @@ AC_SUBST([SRD_PKGLIBS]) # Retrieve the compile and link flags for all modules combined. # Also, bail out at this point if any module dependency is not met. PKG_CHECK_MODULES([LIBSIGROKDECODE], [glib-2.0 >= 2.34 $SRD_PKGLIBS]) +PKG_CHECK_MODULES([LIBIRMP], [glib-2.0 >= 2.34 $SRD_PKGLIBS]) PKG_CHECK_MODULES([TESTS], [$SRD_PKGLIBS_TESTS glib-2.0 $SRD_PKGLIBS]) srd_glib_version=`$PKG_CONFIG --modversion glib-2.0 2>&AS_MESSAGE_LOG_FD` diff --git a/irmp/irmp-main-sharedlib.c b/irmp/irmp-main-sharedlib.c index cbf239a..4d02460 100644 --- a/irmp/irmp-main-sharedlib.c +++ b/irmp/irmp-main-sharedlib.c @@ -3,6 +3,7 @@ * * Copyright (c) 2009-2019 Frank Meyer - frank(at)fli4l.de * Copyright (c) 2009-2019 René Staffen - r.staffen(at)gmx.de + * Copyright (c) 2020-2021 Gerhard Sittig <gerhard.sittig@gmx.net> * * 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 @@ -16,6 +17,9 @@ */ #include "irmp-main-sharedlib.h" +#include <errno.h> +#include <glib.h> +#include <Python.h> #include <stdlib.h> #include <string.h> @@ -98,6 +102,109 @@ # define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif +static int irmp_lib_initialized; +static size_t irmp_lib_client_id; +static GMutex irmp_lib_mutex; + +struct irmp_instance { + size_t client_id; + GMutex *mutex; +}; + +static void irmp_lib_autoinit(void) +{ + if (irmp_lib_initialized) + return; + + irmp_lib_client_id = 0; + g_mutex_init(&irmp_lib_mutex); + + irmp_lib_initialized = 1; +} + +static size_t irmp_next_client_id(void) +{ + size_t id; + + do { + id = ++irmp_lib_client_id; + } while (!id); + + return id; +} + +IRMP_DLLEXPORT struct irmp_instance *irmp_instance_alloc(void) +{ + struct irmp_instance *inst; + + irmp_lib_autoinit(); + + inst = g_malloc0(sizeof(*inst)); + if (!inst) + return NULL; + + inst->client_id = irmp_next_client_id(); + inst->mutex = &irmp_lib_mutex; + + return inst; +} + +IRMP_DLLEXPORT void irmp_instance_free(struct irmp_instance *state) +{ + + irmp_lib_autoinit(); + + if (!state) + return; + + g_free(state); +} + +IRMP_DLLEXPORT size_t irmp_instance_id(struct irmp_instance *state) +{ + + irmp_lib_autoinit(); + + return state ? state->client_id : 0; +} + +IRMP_DLLEXPORT int irmp_instance_lock(struct irmp_instance *state, int wait) +{ + int rc; + PyGILState_STATE pyst; + + irmp_lib_autoinit(); + + if (!state || !state->mutex) + return -EINVAL; + + pyst = PyGILState_Ensure(); + Py_BEGIN_ALLOW_THREADS + if (wait) { + g_mutex_lock(state->mutex); + rc = 0; + } else { + rc = g_mutex_trylock(state->mutex); + } + Py_END_ALLOW_THREADS + PyGILState_Release(pyst); + if (rc != 0) + return rc; + + return 0; +} + +IRMP_DLLEXPORT void irmp_instance_unlock(struct irmp_instance *state) +{ + + irmp_lib_autoinit(); + + if (!state || !state->mutex) + return; + + g_mutex_unlock(state->mutex); +} + static uint32_t s_end_sample; IRMP_DLLEXPORT uint32_t irmp_get_sample_rate(void) @@ -195,3 +302,8 @@ IRMP_DLLEXPORT const char *irmp_get_protocol_name(uint32_t protocol) return "unknown"; return name; } + +static __attribute__((constructor)) void init(void) +{ + irmp_lib_autoinit(); +} diff --git a/irmp/irmp-main-sharedlib.h b/irmp/irmp-main-sharedlib.h index 94065f3..67e7997 100644 --- a/irmp/irmp-main-sharedlib.h +++ b/irmp/irmp-main-sharedlib.h @@ -3,6 +3,7 @@ * * Copyright (c) 2009-2019 Frank Meyer - frank(at)fli4l.de * Copyright (c) 2009-2019 René Staffen - r.staffen(at)gmx.de + * Copyright (c) 2020-2021 Gerhard Sittig <gerhard.sittig@gmx.net> * * 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 @@ -33,6 +34,49 @@ extern "C" { #define WITH_IRMP_DETECT_BUFFER 0 /** + * @brief State container for a decoder core instance. Opaque to clients. + */ +struct irmp_instance; + +/** + * @brief Allocate a decoder instance. + * + * @returns Reference to the allocated instance state. + */ +IRMP_DLLEXPORT struct irmp_instance *irmp_instance_alloc(void); + +/** + * @brief Release a decoder instance. + * + * @param[in] state Reference to the instance's state. + */ +IRMP_DLLEXPORT void irmp_instance_free(struct irmp_instance *state); + +/** + * @brief Get the client ID of an IRMP decoder core instance. + */ +IRMP_DLLEXPORT size_t irmp_instance_id(struct irmp_instance *state); + +/** + * @brief Acquire a decoder instance's lock. + * + * @param[in] state Reference to the instance's state. + * @param[in] wait Whether to block until the lock is acquired. + * + * @returns 0 upon success, non-zero upon failure + */ +IRMP_DLLEXPORT int irmp_instance_lock(struct irmp_instance *state, int wait); + +/** + * @brief Release a decoder instance's lock. + * + * @param[in] state Reference to the instance's state. + * + * @returns 0 upon success, non-zero upon failure + */ +IRMP_DLLEXPORT void irmp_instance_unlock(struct irmp_instance *state); + +/** * @brief IR decoder result data at the library's public API. */ struct irmp_result_data { |