X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=irmp%2Firmp-main-sharedlib.c;h=4d02460014baa4687429bc8cd7a79ad0261c8247;hb=7cfa9f7aa2426c617990f3ecfcabed8765aff46c;hp=baa65c98c83a56998a956a42dcd3769175a91283;hpb=19a0121b2c45d880dab2362d59e1426a5b287a26;p=libsigrokdecode.git diff --git a/irmp/irmp-main-sharedlib.c b/irmp/irmp-main-sharedlib.c index baa65c9..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 * * 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 +#include +#include #include #include @@ -23,7 +27,22 @@ * Include the IRMP core logic. This approach is required because of * static variables which hold internal state. The core logic started * as an MCU project where resources are severely constrained. + * + * This libsigrokdecode incarnation of IRMP will always be used in the + * UNIX_OR_WINDOWS configuration. But libtool(1) breaks the upstream + * logic's platform detection. Check reliably available conditions here + * and provide expected symbols to the library, to reduce changes to the + * upstream project. */ +#if defined _WIN32 +# if !defined WIN32 +# define WIN32 +# endif +#else +# if !defined unix +# define unix +# endif +#endif #include "irmp.h" #include "irmp.c" @@ -83,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) @@ -111,6 +233,19 @@ IRMP_DLLEXPORT void irmp_reset_state(void) s_startBitSample = 0; s_curSample = 0; s_end_sample = 0; + + /* + * TODO This is not the most appropriate location to control the + * core logic's verbosity. But out of the public set of library + * routines this call is closest to some initialization routine. + * The query for compile time parameter values is optional, the + * state reset is not. Multiple verbosity setup activities in + * the same program lifetime won't harm. This HACK is clearly + * preferrable over more fiddling with core logic innards, or + * the introduction of yet another DLL routine. + */ + silent = 1; + verbose = 0; } IRMP_DLLEXPORT int irmp_add_one_sample(int sample) @@ -167,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(); +}