diff options
Diffstat (limited to 'third_party/pipewire/spa/support')
-rw-r--r-- | third_party/pipewire/spa/support/cpu.h | 168 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/dbus.h | 167 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/i18n.h | 107 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/log-impl.h | 143 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/log.h | 314 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/loop.h | 327 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/plugin-loader.h | 101 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/plugin.h | 229 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/system.h | 165 | ||||
-rw-r--r-- | third_party/pipewire/spa/support/thread.h | 149 |
10 files changed, 1870 insertions, 0 deletions
diff --git a/third_party/pipewire/spa/support/cpu.h b/third_party/pipewire/spa/support/cpu.h new file mode 100644 index 0000000000..39a82f426e --- /dev/null +++ b/third_party/pipewire/spa/support/cpu.h @@ -0,0 +1,168 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_CPU_H +#define SPA_CPU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> + +#include <spa/utils/defs.h> +#include <spa/utils/hook.h> + +/** \defgroup spa_cpu CPU + * Querying CPU properties + */ + +/** + * \addtogroup spa_cpu + * \{ + */ + +/** + * The CPU features interface + */ +#define SPA_TYPE_INTERFACE_CPU SPA_TYPE_INFO_INTERFACE_BASE "CPU" + +#define SPA_VERSION_CPU 0 +struct spa_cpu { struct spa_interface iface; }; + +/* x86 specific */ +#define SPA_CPU_FLAG_MMX (1<<0) /**< standard MMX */ +#define SPA_CPU_FLAG_MMXEXT (1<<1) /**< SSE integer or AMD MMX ext */ +#define SPA_CPU_FLAG_3DNOW (1<<2) /**< AMD 3DNOW */ +#define SPA_CPU_FLAG_SSE (1<<3) /**< SSE */ +#define SPA_CPU_FLAG_SSE2 (1<<4) /**< SSE2 */ +#define SPA_CPU_FLAG_3DNOWEXT (1<<5) /**< AMD 3DNowExt */ +#define SPA_CPU_FLAG_SSE3 (1<<6) /**< Prescott SSE3 */ +#define SPA_CPU_FLAG_SSSE3 (1<<7) /**< Conroe SSSE3 */ +#define SPA_CPU_FLAG_SSE41 (1<<8) /**< Penryn SSE4.1 */ +#define SPA_CPU_FLAG_SSE42 (1<<9) /**< Nehalem SSE4.2 */ +#define SPA_CPU_FLAG_AESNI (1<<10) /**< Advanced Encryption Standard */ +#define SPA_CPU_FLAG_AVX (1<<11) /**< AVX */ +#define SPA_CPU_FLAG_XOP (1<<12) /**< Bulldozer XOP */ +#define SPA_CPU_FLAG_FMA4 (1<<13) /**< Bulldozer FMA4 */ +#define SPA_CPU_FLAG_CMOV (1<<14) /**< supports cmov */ +#define SPA_CPU_FLAG_AVX2 (1<<15) /**< AVX2 */ +#define SPA_CPU_FLAG_FMA3 (1<<16) /**< Haswell FMA3 */ +#define SPA_CPU_FLAG_BMI1 (1<<17) /**< Bit Manipulation Instruction Set 1 */ +#define SPA_CPU_FLAG_BMI2 (1<<18) /**< Bit Manipulation Instruction Set 2 */ +#define SPA_CPU_FLAG_AVX512 (1<<19) /**< AVX-512 */ +#define SPA_CPU_FLAG_SLOW_UNALIGNED (1<<20) /**< unaligned loads/stores are slow */ + +/* PPC specific */ +#define SPA_CPU_FLAG_ALTIVEC (1<<0) /**< standard */ +#define SPA_CPU_FLAG_VSX (1<<1) /**< ISA 2.06 */ +#define SPA_CPU_FLAG_POWER8 (1<<2) /**< ISA 2.07 */ + +/* ARM specific */ +#define SPA_CPU_FLAG_ARMV5TE (1 << 0) +#define SPA_CPU_FLAG_ARMV6 (1 << 1) +#define SPA_CPU_FLAG_ARMV6T2 (1 << 2) +#define SPA_CPU_FLAG_VFP (1 << 3) +#define SPA_CPU_FLAG_VFPV3 (1 << 4) +#define SPA_CPU_FLAG_NEON (1 << 5) +#define SPA_CPU_FLAG_ARMV8 (1 << 6) + +#define SPA_CPU_FORCE_AUTODETECT ((uint32_t)-1) + +#define SPA_CPU_VM_NONE (0) +#define SPA_CPU_VM_OTHER (1 << 0) +#define SPA_CPU_VM_KVM (1 << 1) +#define SPA_CPU_VM_QEMU (1 << 2) +#define SPA_CPU_VM_BOCHS (1 << 3) +#define SPA_CPU_VM_XEN (1 << 4) +#define SPA_CPU_VM_UML (1 << 5) +#define SPA_CPU_VM_VMWARE (1 << 6) +#define SPA_CPU_VM_ORACLE (1 << 7) +#define SPA_CPU_VM_MICROSOFT (1 << 8) +#define SPA_CPU_VM_ZVM (1 << 9) +#define SPA_CPU_VM_PARALLELS (1 << 10) +#define SPA_CPU_VM_BHYVE (1 << 11) +#define SPA_CPU_VM_QNX (1 << 12) +#define SPA_CPU_VM_ACRN (1 << 13) +#define SPA_CPU_VM_POWERVM (1 << 14) + +/** + * methods + */ +struct spa_cpu_methods { + /** the version of the methods. This can be used to expand this + structure in the future */ +#define SPA_VERSION_CPU_METHODS 2 + uint32_t version; + + /** get CPU flags */ + uint32_t (*get_flags) (void *object); + + /** force CPU flags, use SPA_CPU_FORCE_AUTODETECT to autodetect CPU flags */ + int (*force_flags) (void *object, uint32_t flags); + + /** get number of CPU cores */ + uint32_t (*get_count) (void *object); + + /** get maximum required alignment of data */ + uint32_t (*get_max_align) (void *object); + + /* check if running in a VM. Since:1 */ + uint32_t (*get_vm_type) (void *object); + + /* denormals will be handled as zero, either with FTZ or DAZ. + * Since:2 */ + int (*zero_denormals) (void *object, bool enable); +}; + +#define spa_cpu_method(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_cpu *_c = o; \ + spa_interface_call_res(&_c->iface, \ + struct spa_cpu_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) +#define spa_cpu_get_flags(c) spa_cpu_method(c, get_flags, 0) +#define spa_cpu_force_flags(c,f) spa_cpu_method(c, force_flags, 0, f) +#define spa_cpu_get_count(c) spa_cpu_method(c, get_count, 0) +#define spa_cpu_get_max_align(c) spa_cpu_method(c, get_max_align, 0) +#define spa_cpu_get_vm_type(c) spa_cpu_method(c, get_vm_type, 1) +#define spa_cpu_zero_denormals(c,e) spa_cpu_method(c, zero_denormals, 2, e) + +/** keys can be given when initializing the cpu handle */ +#define SPA_KEY_CPU_FORCE "cpu.force" /**< force cpu flags */ +#define SPA_KEY_CPU_VM_TYPE "cpu.vm.type" /**< force a VM type */ +#define SPA_KEY_CPU_ZERO_DENORMALS "cpu.zero.denormals" /**< zero denormals */ + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_CPU_H */ diff --git a/third_party/pipewire/spa/support/dbus.h b/third_party/pipewire/spa/support/dbus.h new file mode 100644 index 0000000000..9ebb7d8355 --- /dev/null +++ b/third_party/pipewire/spa/support/dbus.h @@ -0,0 +1,167 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_DBUS_H +#define SPA_DBUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/support/loop.h> + +/** \defgroup spa_dbus DBus + * DBus communication + */ + +/** + * \addtogroup spa_dbus + * \{ + */ + +#define SPA_TYPE_INTERFACE_DBus SPA_TYPE_INFO_INTERFACE_BASE "DBus" + +#define SPA_VERSION_DBUS 0 +struct spa_dbus { struct spa_interface iface; }; + +enum spa_dbus_type { + SPA_DBUS_TYPE_SESSION, /**< The login session bus */ + SPA_DBUS_TYPE_SYSTEM, /**< The systemwide bus */ + SPA_DBUS_TYPE_STARTER /**< The bus that started us, if any */ +}; + +#define SPA_DBUS_CONNECTION_EVENT_DESTROY 0 +#define SPA_DBUS_CONNECTION_EVENT_DISCONNECTED 1 +#define SPA_DBUS_CONNECTION_EVENT_NUM 2 + +struct spa_dbus_connection_events { +#define SPA_VERSION_DBUS_CONNECTION_EVENTS 0 + uint32_t version; + + /* a connection is destroyed */ + void (*destroy) (void *data); + + /* a connection disconnected */ + void (*disconnected) (void *data); +}; + +struct spa_dbus_connection { +#define SPA_VERSION_DBUS_CONNECTION 1 + uint32_t version; + /** + * Get the DBusConnection from a wrapper + * + * Note that the returned handle is closed and unref'd by spa_dbus + * immediately before emitting the asynchronous "disconnected" event. + * The caller must either deal with the invalidation, or keep an extra + * ref on the handle returned. + * + * \param conn the spa_dbus_connection wrapper + * \return a pointer of type DBusConnection + */ + void *(*get) (struct spa_dbus_connection *conn); + /** + * Destroy a dbus connection wrapper + * + * \param conn the wrapper to destroy + */ + void (*destroy) (struct spa_dbus_connection *conn); + + /** + * Add a listener for events + * + * Since version 1 + */ + void (*add_listener) (struct spa_dbus_connection *conn, + struct spa_hook *listener, + const struct spa_dbus_connection_events *events, + void *data); +}; + +#define spa_dbus_connection_call(c,method,vers,...) \ +({ \ + if (SPA_LIKELY(SPA_CALLBACK_CHECK(c,method,vers))) \ + c->method((c), ## __VA_ARGS__); \ +}) + +#define spa_dbus_connection_call_vp(c,method,vers,...) \ +({ \ + void *_res = NULL; \ + if (SPA_LIKELY(SPA_CALLBACK_CHECK(c,method,vers))) \ + _res = c->method((c), ## __VA_ARGS__); \ + _res; \ +}) + +/** \copydoc spa_dbus_connection.get + * \sa spa_dbus_connection.get */ +#define spa_dbus_connection_get(c) spa_dbus_connection_call_vp(c,get,0) +/** \copydoc spa_dbus_connection.destroy + * \sa spa_dbus_connection.destroy */ +#define spa_dbus_connection_destroy(c) spa_dbus_connection_call(c,destroy,0) +/** \copydoc spa_dbus_connection.add_listener + * \sa spa_dbus_connection.add_listener */ +#define spa_dbus_connection_add_listener(c,...) spa_dbus_connection_call(c,add_listener,1,__VA_ARGS__) + +struct spa_dbus_methods { +#define SPA_VERSION_DBUS_METHODS 0 + uint32_t version; + + /** + * Get a new connection wrapper for the given bus type. + * + * The connection wrapper is completely configured to operate + * in the main context of the handle that manages the spa_dbus + * interface. + * + * \param dbus the dbus manager + * \param type the bus type to wrap + * \param error location for the DBusError + * \return a new dbus connection wrapper or NULL on error + */ + struct spa_dbus_connection * (*get_connection) (void *object, + enum spa_dbus_type type); +}; + +/** \copydoc spa_dbus_methods.get_connection + * \sa spa_dbus_methods.get_connection + */ +static inline struct spa_dbus_connection * +spa_dbus_get_connection(struct spa_dbus *dbus, enum spa_dbus_type type) +{ + struct spa_dbus_connection *res = NULL; + spa_interface_call_res(&dbus->iface, + struct spa_dbus_methods, res, + get_connection, 0, type); + return res; +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_DBUS_H */ diff --git a/third_party/pipewire/spa/support/i18n.h b/third_party/pipewire/spa/support/i18n.h new file mode 100644 index 0000000000..fc45b0734e --- /dev/null +++ b/third_party/pipewire/spa/support/i18n.h @@ -0,0 +1,107 @@ +/* Simple Plugin API + * + * Copyright © 2021 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_I18N_H +#define SPA_I18N_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/utils/hook.h> +#include <spa/utils/defs.h> + +/** \defgroup spa_i18n I18N + * Gettext interface + */ + +/** + * \addtogroup spa_i18n + * \{ + */ + +#define SPA_TYPE_INTERFACE_I18N SPA_TYPE_INFO_INTERFACE_BASE "I18N" + +#define SPA_VERSION_I18N 0 +struct spa_i18n { struct spa_interface iface; }; + +struct spa_i18n_methods { +#define SPA_VERSION_I18N_METHODS 0 + uint32_t version; + + /** + * Translate a message + * + * \param object the i18n interface + * \param msgid the message + * \return a translated message + */ + const char *(*text) (void *object, const char *msgid); + + /** + * Translate a message for a number + * + * \param object the i18n interface + * \param msgid the message to translate + * \param msgid_plural the plural form of \a msgid + * \param n a number + * \return a translated message for the number \a n + */ + const char *(*ntext) (void *object, const char *msgid, + const char *msgid_plural, unsigned long int n); +}; + +SPA_FORMAT_ARG_FUNC(2) +static inline const char * +spa_i18n_text(struct spa_i18n *i18n, const char *msgid) +{ + const char *res = msgid; + if (SPA_LIKELY(i18n != NULL)) + spa_interface_call_res(&i18n->iface, + struct spa_i18n_methods, res, + text, 0, msgid); + return res; +} + +static inline const char * +spa_i18n_ntext(struct spa_i18n *i18n, const char *msgid, + const char *msgid_plural, unsigned long int n) +{ + const char *res = n == 1 ? msgid : msgid_plural; + if (SPA_LIKELY(i18n != NULL)) + spa_interface_call_res(&i18n->iface, + struct spa_i18n_methods, res, + ntext, 0, msgid, msgid_plural, n); + return res; +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_I18N_H */ diff --git a/third_party/pipewire/spa/support/log-impl.h b/third_party/pipewire/spa/support/log-impl.h new file mode 100644 index 0000000000..124153d073 --- /dev/null +++ b/third_party/pipewire/spa/support/log-impl.h @@ -0,0 +1,143 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_LOG_IMPL_H +#define SPA_LOG_IMPL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> + +#include <spa/utils/type.h> +#include <spa/support/log.h> + +/** + * \addtogroup spa_log + * \{ + */ + +static inline SPA_PRINTF_FUNC(7, 0) void spa_log_impl_logtv(void *object, + enum spa_log_level level, + const struct spa_log_topic *topic, + const char *file, + int line, + const char *func, + const char *fmt, + va_list args) +{ + static const char * const levels[] = { "-", "E", "W", "I", "D", "T" }; + + const char *basename = strrchr(file, '/'); + char text[512], location[1024]; + char topicstr[32] = {0}; + + if (basename) + basename += 1; /* skip '/' */ + else + basename = file; /* use whole string if no '/' is found */ + + if (topic && topic->topic) + snprintf(topicstr, sizeof(topicstr), " %s ", topic->topic); + vsnprintf(text, sizeof(text), fmt, args); + snprintf(location, sizeof(location), "[%s]%s[%s:%i %s()] %s\n", + levels[level], + topicstr, + basename, line, func, text); + fputs(location, stderr); +} + +static inline SPA_PRINTF_FUNC(7,8) void spa_log_impl_logt(void *object, + enum spa_log_level level, + const struct spa_log_topic *topic, + const char *file, + int line, + const char *func, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + spa_log_impl_logtv(object, level, topic, file, line, func, fmt, args); + va_end(args); +} + +static inline SPA_PRINTF_FUNC(6, 0) void spa_log_impl_logv(void *object, + enum spa_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, + va_list args) +{ + + spa_log_impl_logtv(object, level, NULL, file, line, func, fmt, args); +} + +static inline SPA_PRINTF_FUNC(6,7) void spa_log_impl_log(void *object, + enum spa_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + spa_log_impl_logv(object, level, file, line, func, fmt, args); + va_end(args); +} + +static inline void spa_log_impl_topic_init(void *object, struct spa_log_topic *topic) +{ + /* noop */ +} + +#define SPA_LOG_IMPL_DEFINE(name) \ +struct { \ + struct spa_log log; \ + struct spa_log_methods methods; \ +} name + +#define SPA_LOG_IMPL_INIT(name) \ + { { { SPA_TYPE_INTERFACE_Log, SPA_VERSION_LOG, \ + SPA_CALLBACKS_INIT(&name.methods, &name) }, \ + SPA_LOG_LEVEL_INFO, }, \ + { SPA_VERSION_LOG_METHODS, \ + spa_log_impl_log, \ + spa_log_impl_logv, \ + spa_log_impl_logt, \ + spa_log_impl_logtv, \ + } } + +#define SPA_LOG_IMPL(name) \ + SPA_LOG_IMPL_DEFINE(name) = SPA_LOG_IMPL_INIT(name) + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* SPA_LOG_IMPL_H */ diff --git a/third_party/pipewire/spa/support/log.h b/third_party/pipewire/spa/support/log.h new file mode 100644 index 0000000000..e4990d1bb6 --- /dev/null +++ b/third_party/pipewire/spa/support/log.h @@ -0,0 +1,314 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_LOG_H +#define SPA_LOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> + +#include <spa/utils/type.h> +#include <spa/utils/defs.h> +#include <spa/utils/hook.h> + +/** \defgroup spa_log Log + * Logging interface + */ + +/** + * \addtogroup spa_log + * \{ + */ + +/** The default log topic. Redefine this in your code to + * allow for the spa_log_* macros to work correctly, e.g: + * + * \code{.c} + * struct spa_log_topic *mylogger; + * #undef SPA_LOG_TOPIC_DEFAULT + * #define SPA_LOG_TOPIC_DEFAULT mylogger + * \endcode + */ +#define SPA_LOG_TOPIC_DEFAULT NULL + +enum spa_log_level { + SPA_LOG_LEVEL_NONE = 0, + SPA_LOG_LEVEL_ERROR, + SPA_LOG_LEVEL_WARN, + SPA_LOG_LEVEL_INFO, + SPA_LOG_LEVEL_DEBUG, + SPA_LOG_LEVEL_TRACE, +}; + +/** + * The Log interface + */ +#define SPA_TYPE_INTERFACE_Log SPA_TYPE_INFO_INTERFACE_BASE "Log" + + +struct spa_log { + /** the version of this log. This can be used to expand this + * structure in the future */ +#define SPA_VERSION_LOG 0 + struct spa_interface iface; + /** + * Logging level, everything above this level is not logged + */ + enum spa_log_level level; +}; + +/** + * \struct spa_log_topic + * + * Identifier for a topic. Topics are string-based filters that logically + * group messages together. An implementation may decide to filter different + * topics on different levels, for example the "protocol" topic may require + * debug level TRACE while the "core" topic defaults to debug level INFO. + * + * spa_log_topics require a spa_log_methods version of 1 or higher. + */ +struct spa_log_topic { +#define SPA_VERSION_LOG_TOPIC 0 + /** the version of this topic. This can be used to expand this + * structure in the future */ + uint32_t version; + /** The string identifier for the topic */ + const char *topic; + /** Logging level set for this topic */ + enum spa_log_level level; + /** False if this topic follows the \ref spa_log level */ + bool has_custom_level; +}; + +struct spa_log_methods { +#define SPA_VERSION_LOG_METHODS 1 + uint32_t version; + /** + * Log a message with the given log level. + * + * \note If compiled with this header, this function is only called + * for implementations of version 0. For versions 1 and above, see + * logt() instead. + * + * \param log a spa_log + * \param level a spa_log_level + * \param file the file name + * \param line the line number + * \param func the function name + * \param fmt printf style format + * \param ... format arguments + */ + void (*log) (void *object, + enum spa_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, ...) SPA_PRINTF_FUNC(6, 7); + + /** + * Log a message with the given log level. + * + * \note If compiled with this header, this function is only called + * for implementations of version 0. For versions 1 and above, see + * logtv() instead. + * + * \param log a spa_log + * \param level a spa_log_level + * \param file the file name + * \param line the line number + * \param func the function name + * \param fmt printf style format + * \param args format arguments + */ + void (*logv) (void *object, + enum spa_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, + va_list args) SPA_PRINTF_FUNC(6, 0); + /** + * Log a message with the given log level for the given topic. + * + * \note Callers that do not use topic-based logging (version 0), the \a + * topic is NULL + * + * \param log a spa_log + * \param level a spa_log_level + * \param topic the topic for this message, may be NULL + * \param file the file name + * \param line the line number + * \param func the function name + * \param fmt printf style format + * \param ... format arguments + * + * \since 1 + */ + void (*logt) (void *object, + enum spa_log_level level, + const struct spa_log_topic *topic, + const char *file, + int line, + const char *func, + const char *fmt, ...) SPA_PRINTF_FUNC(7, 8); + + /** + * Log a message with the given log level for the given topic. + * + * \note For callers that do not use topic-based logging (version 0), + * the \a topic is NULL + * + * \param log a spa_log + * \param level a spa_log_level + * \param topic the topic for this message, may be NULL + * \param file the file name + * \param line the line number + * \param func the function name + * \param fmt printf style format + * \param args format arguments + * + * \since 1 + */ + void (*logtv) (void *object, + enum spa_log_level level, + const struct spa_log_topic *topic, + const char *file, + int line, + const char *func, + const char *fmt, + va_list args) SPA_PRINTF_FUNC(7, 0); + + /** + * Initializes a \ref spa_log_topic to the correct logging level. + * + * \since 1 + */ + void (*topic_init) (void *object, struct spa_log_topic *topic); +}; + + +#define SPA_LOG_TOPIC(v, t) \ + (struct spa_log_topic){ .version = v, .topic = (t)} + +#define spa_log_topic_init(l, topic) \ +do { \ + struct spa_log *_l = l; \ + if (SPA_LIKELY(_l)) { \ + struct spa_interface *_if = &_l->iface; \ + spa_interface_call(_if, struct spa_log_methods, \ + topic_init, 1, topic); \ + } \ +} while(0) + +/* Unused, left for backwards compat */ +#define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev)) + +#define spa_log_level_topic_enabled(l,topic,lev) \ +({ \ + struct spa_log *_log = l; \ + enum spa_log_level _lev = _log ? _log->level : SPA_LOG_LEVEL_NONE; \ + struct spa_log_topic *_t = (struct spa_log_topic *)topic; \ + if (_t && _t->has_custom_level) \ + _lev = _t->level; \ + _lev >= lev; \ +}) + +/* Transparently calls to version 0 log if v1 is not supported */ +#define spa_log_logt(l,lev,topic,...) \ +({ \ + struct spa_log *_l = l; \ + struct spa_interface *_if = &_l->iface; \ + if (SPA_UNLIKELY(spa_log_level_topic_enabled(_l, topic, lev))) { \ + if (!spa_interface_call(_if, \ + struct spa_log_methods, logt, 1, \ + lev, topic, \ + __VA_ARGS__)) \ + spa_interface_call(_if, \ + struct spa_log_methods, log, 0, \ + lev, __VA_ARGS__); \ + } \ +}) + +/* Transparently calls to version 0 logv if v1 is not supported */ +#define spa_log_logtv(l,lev,topic,...) \ +({ \ + struct spa_log *_l = l; \ + struct spa_interface *_if = &_l->iface; \ + if (SPA_UNLIKELY(spa_log_level_topic_enabled(_l, topic, lev))) { \ + if (!spa_interface_call(_if, \ + struct spa_log_methods, logtv, 1, \ + lev, topic, \ + __VA_ARGS__)) \ + spa_interface_call(_if, \ + struct spa_log_methods, logv, 0, \ + lev, __VA_ARGS__); \ + } \ +}) + +#define spa_log_log(l,lev,...) \ + spa_log_logt(l,lev,SPA_LOG_TOPIC_DEFAULT,__VA_ARGS__) + +#define spa_log_logv(l,lev,...) \ + spa_log_logtv(l,lev,SPA_LOG_TOPIC_DEFAULT,__VA_ARGS__) + +#define spa_log_error(l,...) spa_log_log(l,SPA_LOG_LEVEL_ERROR,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_log_warn(l,...) spa_log_log(l,SPA_LOG_LEVEL_WARN,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_log_info(l,...) spa_log_log(l,SPA_LOG_LEVEL_INFO,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_log_debug(l,...) spa_log_log(l,SPA_LOG_LEVEL_DEBUG,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_log_trace(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) + +#define spa_logt_error(l,t,...) spa_log_logt(l,SPA_LOG_LEVEL_ERROR,t,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_logt_warn(l,t,...) spa_log_logt(l,SPA_LOG_LEVEL_WARN,t,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_logt_info(l,t,...) spa_log_logt(l,SPA_LOG_LEVEL_INFO,t,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_logt_debug(l,t,...) spa_log_logt(l,SPA_LOG_LEVEL_DEBUG,t,__FILE__,__LINE__,__func__,__VA_ARGS__) +#define spa_logt_trace(l,t,...) spa_log_logt(l,SPA_LOG_LEVEL_TRACE,t,__FILE__,__LINE__,__func__,__VA_ARGS__) + +#ifndef FASTPATH +#define spa_log_trace_fp(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) +#else +#define spa_log_trace_fp(l,...) +#endif + +/** \fn spa_log_error */ + +/** keys can be given when initializing the logger handle */ +#define SPA_KEY_LOG_LEVEL "log.level" /**< the default log level */ +#define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger */ +#define SPA_KEY_LOG_FILE "log.file" /**< log to the specified file instead of + * stderr. */ +#define SPA_KEY_LOG_TIMESTAMP "log.timestamp" /**< log timestamps */ +#define SPA_KEY_LOG_LINE "log.line" /**< log file and line numbers */ +#define SPA_KEY_LOG_PATTERNS "log.patterns" /**< Spa:String:JSON array of [ {"pattern" : level}, ... ] */ + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* SPA_LOG_H */ diff --git a/third_party/pipewire/spa/support/loop.h b/third_party/pipewire/spa/support/loop.h new file mode 100644 index 0000000000..3c93573c8f --- /dev/null +++ b/third_party/pipewire/spa/support/loop.h @@ -0,0 +1,327 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_LOOP_H +#define SPA_LOOP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/utils/defs.h> +#include <spa/utils/hook.h> +#include <spa/support/system.h> + +/** \defgroup spa_loop Loop + * Event loop interface + */ + +/** + * \addtogroup spa_loop + * \{ + */ + +#define SPA_TYPE_INTERFACE_Loop SPA_TYPE_INFO_INTERFACE_BASE "Loop" +#define SPA_TYPE_INTERFACE_DataLoop SPA_TYPE_INFO_INTERFACE_BASE "DataLoop" +#define SPA_VERSION_LOOP 0 +struct spa_loop { struct spa_interface iface; }; + +#define SPA_TYPE_INTERFACE_LoopControl SPA_TYPE_INFO_INTERFACE_BASE "LoopControl" +#define SPA_VERSION_LOOP_CONTROL 0 +struct spa_loop_control { struct spa_interface iface; }; + +#define SPA_TYPE_INTERFACE_LoopUtils SPA_TYPE_INFO_INTERFACE_BASE "LoopUtils" +#define SPA_VERSION_LOOP_UTILS 0 +struct spa_loop_utils { struct spa_interface iface; }; + +struct spa_source; + +typedef void (*spa_source_func_t) (struct spa_source *source); + +struct spa_source { + struct spa_loop *loop; + spa_source_func_t func; + void *data; + int fd; + uint32_t mask; + uint32_t rmask; + /* private data for the loop implementer */ + void *priv; +}; + +typedef int (*spa_invoke_func_t) (struct spa_loop *loop, + bool async, + uint32_t seq, + const void *data, + size_t size, + void *user_data); + +/** + * Register sources and work items to an event loop + */ +struct spa_loop_methods { + /* the version of this structure. This can be used to expand this + * structure in the future */ +#define SPA_VERSION_LOOP_METHODS 0 + uint32_t version; + + /** add a source to the loop */ + int (*add_source) (void *object, + struct spa_source *source); + + /** update the source io mask */ + int (*update_source) (void *object, + struct spa_source *source); + + /** remove a source from the loop */ + int (*remove_source) (void *object, + struct spa_source *source); + + /** invoke a function in the context of this loop */ + int (*invoke) (void *object, + spa_invoke_func_t func, + uint32_t seq, + const void *data, + size_t size, + bool block, + void *user_data); +}; + +#define spa_loop_method(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_loop *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_loop_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) + +#define spa_loop_add_source(l,...) spa_loop_method(l,add_source,0,##__VA_ARGS__) +#define spa_loop_update_source(l,...) spa_loop_method(l,update_source,0,##__VA_ARGS__) +#define spa_loop_remove_source(l,...) spa_loop_method(l,remove_source,0,##__VA_ARGS__) +#define spa_loop_invoke(l,...) spa_loop_method(l,invoke,0,##__VA_ARGS__) + + +/** Control hooks. These hooks can't be removed from their + * callbacks and must be removed from a safe place (when the loop + * is not running or when it is locked). */ +struct spa_loop_control_hooks { +#define SPA_VERSION_LOOP_CONTROL_HOOKS 0 + uint32_t version; + /** Executed right before waiting for events. It is typically used to + * release locks. */ + void (*before) (void *data); + /** Executed right after waiting for events. It is typically used to + * reacquire locks. */ + void (*after) (void *data); +}; + +#define spa_loop_control_hook_before(l) \ +({ \ + struct spa_hook_list *_l = l; \ + struct spa_hook *_h; \ + spa_list_for_each_reverse(_h, &_l->list, link) \ + spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, before, 0); \ +}) + +#define spa_loop_control_hook_after(l) \ +({ \ + struct spa_hook_list *_l = l; \ + struct spa_hook *_h; \ + spa_list_for_each(_h, &_l->list, link) \ + spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, after, 0); \ +}) + +/** + * Control an event loop + */ +struct spa_loop_control_methods { + /* the version of this structure. This can be used to expand this + * structure in the future */ +#define SPA_VERSION_LOOP_CONTROL_METHODS 0 + uint32_t version; + + int (*get_fd) (void *object); + + /** Add a hook + * \param ctrl the control to change + * \param hooks the hooks to add + * + * Adds hooks to the loop controlled by \a ctrl. + */ + void (*add_hook) (void *object, + struct spa_hook *hook, + const struct spa_loop_control_hooks *hooks, + void *data); + + /** Enter a loop + * \param ctrl the control + * + * Start an iteration of the loop. This function should be called + * before calling iterate and is typically used to capture the thread + * that this loop will run in. + */ + void (*enter) (void *object); + /** Leave a loop + * \param ctrl the control + * + * Ends the iteration of a loop. This should be called after calling + * iterate. + */ + void (*leave) (void *object); + + /** Perform one iteration of the loop. + * \param ctrl the control + * \param timeout an optional timeout in milliseconds. + * 0 for no timeout, -1 for infinite timeout. + * + * This function will block + * up to \a timeout milliseconds and then dispatch the fds with activity. + * The number of dispatched fds is returned. + */ + int (*iterate) (void *object, int timeout); +}; + +#define spa_loop_control_method_v(o,method,version,...) \ +({ \ + struct spa_loop_control *_o = o; \ + spa_interface_call(&_o->iface, \ + struct spa_loop_control_methods, \ + method, version, ##__VA_ARGS__); \ +}) + +#define spa_loop_control_method_r(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_loop_control *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_loop_control_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) + +#define spa_loop_control_get_fd(l) spa_loop_control_method_r(l,get_fd,0) +#define spa_loop_control_add_hook(l,...) spa_loop_control_method_v(l,add_hook,0,__VA_ARGS__) +#define spa_loop_control_enter(l) spa_loop_control_method_v(l,enter,0) +#define spa_loop_control_leave(l) spa_loop_control_method_v(l,leave,0) +#define spa_loop_control_iterate(l,...) spa_loop_control_method_r(l,iterate,0,__VA_ARGS__) + +typedef void (*spa_source_io_func_t) (void *data, int fd, uint32_t mask); +typedef void (*spa_source_idle_func_t) (void *data); +typedef void (*spa_source_event_func_t) (void *data, uint64_t count); +typedef void (*spa_source_timer_func_t) (void *data, uint64_t expirations); +typedef void (*spa_source_signal_func_t) (void *data, int signal_number); + +/** + * Create sources for an event loop + */ +struct spa_loop_utils_methods { + /* the version of this structure. This can be used to expand this + * structure in the future */ +#define SPA_VERSION_LOOP_UTILS_METHODS 0 + uint32_t version; + + struct spa_source *(*add_io) (void *object, + int fd, + uint32_t mask, + bool close, + spa_source_io_func_t func, void *data); + + int (*update_io) (void *object, struct spa_source *source, uint32_t mask); + + struct spa_source *(*add_idle) (void *object, + bool enabled, + spa_source_idle_func_t func, void *data); + int (*enable_idle) (void *object, struct spa_source *source, bool enabled); + + struct spa_source *(*add_event) (void *object, + spa_source_event_func_t func, void *data); + int (*signal_event) (void *object, struct spa_source *source); + + struct spa_source *(*add_timer) (void *object, + spa_source_timer_func_t func, void *data); + int (*update_timer) (void *object, + struct spa_source *source, + struct timespec *value, + struct timespec *interval, + bool absolute); + struct spa_source *(*add_signal) (void *object, + int signal_number, + spa_source_signal_func_t func, void *data); + + /** destroy a source allocated with this interface. This function + * should only be called when the loop is not running or from the + * context of the running loop */ + void (*destroy_source) (void *object, struct spa_source *source); +}; + +#define spa_loop_utils_method_v(o,method,version,...) \ +({ \ + struct spa_loop_utils *_o = o; \ + spa_interface_call(&_o->iface, \ + struct spa_loop_utils_methods, \ + method, version, ##__VA_ARGS__); \ +}) + +#define spa_loop_utils_method_r(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_loop_utils *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_loop_utils_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) +#define spa_loop_utils_method_s(o,method,version,...) \ +({ \ + struct spa_source *_res = NULL; \ + struct spa_loop_utils *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_loop_utils_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) + + +#define spa_loop_utils_add_io(l,...) spa_loop_utils_method_s(l,add_io,0,__VA_ARGS__) +#define spa_loop_utils_update_io(l,...) spa_loop_utils_method_r(l,update_io,0,__VA_ARGS__) +#define spa_loop_utils_add_idle(l,...) spa_loop_utils_method_s(l,add_idle,0,__VA_ARGS__) +#define spa_loop_utils_enable_idle(l,...) spa_loop_utils_method_r(l,enable_idle,0,__VA_ARGS__) +#define spa_loop_utils_add_event(l,...) spa_loop_utils_method_s(l,add_event,0,__VA_ARGS__) +#define spa_loop_utils_signal_event(l,...) spa_loop_utils_method_r(l,signal_event,0,__VA_ARGS__) +#define spa_loop_utils_add_timer(l,...) spa_loop_utils_method_s(l,add_timer,0,__VA_ARGS__) +#define spa_loop_utils_update_timer(l,...) spa_loop_utils_method_r(l,update_timer,0,__VA_ARGS__) +#define spa_loop_utils_add_signal(l,...) spa_loop_utils_method_s(l,add_signal,0,__VA_ARGS__) +#define spa_loop_utils_destroy_source(l,...) spa_loop_utils_method_v(l,destroy_source,0,__VA_ARGS__) + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_LOOP_H */ diff --git a/third_party/pipewire/spa/support/plugin-loader.h b/third_party/pipewire/spa/support/plugin-loader.h new file mode 100644 index 0000000000..ced58cbce2 --- /dev/null +++ b/third_party/pipewire/spa/support/plugin-loader.h @@ -0,0 +1,101 @@ +/* Simple Plugin API + * + * Copyright © 2021 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_PLUGIN_LOADER_H +#define SPA_PLUGIN_LOADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/utils/hook.h> +#include <spa/utils/dict.h> + +/** \defgroup spa_plugin_loader Plugin Loader + * SPA plugin loader + */ + +/** + * \addtogroup spa_plugin_loader + * \{ + */ + +#define SPA_TYPE_INTERFACE_PluginLoader SPA_TYPE_INFO_INTERFACE_BASE "PluginLoader" + +#define SPA_VERSION_PLUGIN_LOADER 0 +struct spa_plugin_loader { struct spa_interface iface; }; + +struct spa_plugin_loader_methods { +#define SPA_VERSION_PLUGIN_LOADER_METHODS 0 + uint32_t version; + + /** + * Load a SPA plugin. + * + * \param factory_name Plugin factory name + * \param info Info dictionary for plugin. NULL if none. + * \return plugin handle, or NULL on error + */ + struct spa_handle *(*load) (void *object, const char *factory_name, const struct spa_dict *info); + + /** + * Unload a SPA plugin. + * + * \param handle Plugin handle. + * \return 0 on success, < 0 on error + */ + int (*unload)(void *object, struct spa_handle *handle); +}; + +static inline struct spa_handle * +spa_plugin_loader_load(struct spa_plugin_loader *loader, const char *factory_name, const struct spa_dict *info) +{ + struct spa_handle *res = NULL; + if (SPA_LIKELY(loader != NULL)) + spa_interface_call_res(&loader->iface, + struct spa_plugin_loader_methods, res, + load, 0, factory_name, info); + return res; +} + +static inline int +spa_plugin_loader_unload(struct spa_plugin_loader *loader, struct spa_handle *handle) +{ + int res = -1; + if (SPA_LIKELY(loader != NULL)) + spa_interface_call_res(&loader->iface, + struct spa_plugin_loader_methods, res, + unload, 0, handle); + return res; +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PLUGIN_LOADER_H */ diff --git a/third_party/pipewire/spa/support/plugin.h b/third_party/pipewire/spa/support/plugin.h new file mode 100644 index 0000000000..e66bdc9976 --- /dev/null +++ b/third_party/pipewire/spa/support/plugin.h @@ -0,0 +1,229 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_PLUGIN_H +#define SPA_PLUGIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/utils/defs.h> +#include <spa/utils/dict.h> + +/** + * \defgroup spa_handle Plugin Handle + * SPA plugin handle and factory interfaces + */ + +/** + * \addtogroup spa_handle + * \{ + */ + +struct spa_handle { + /** Version of this struct */ +#define SPA_VERSION_HANDLE 0 + uint32_t version; + + /** + * Get the interface provided by \a handle with \a type. + * + * \a interface is always a struct spa_interface but depending on + * \a type, the struct might contain other information. + * + * \param handle a spa_handle + * \param type the interface type + * \param interface result to hold the interface. + * \return 0 on success + * -ENOTSUP when there are no interfaces + * -EINVAL when handle or info is NULL + */ + int (*get_interface) (struct spa_handle *handle, const char *type, void **interface); + /** + * Clean up the memory of \a handle. After this, \a handle should not be used + * anymore. + * + * \param handle a pointer to memory + * \return 0 on success + */ + int (*clear) (struct spa_handle *handle); +}; + +#define spa_handle_get_interface(h,...) (h)->get_interface((h),__VA_ARGS__) +#define spa_handle_clear(h) (h)->clear((h)) + +/** + * This structure lists the information about available interfaces on + * handles. + */ +struct spa_interface_info { + const char *type; /*< the type of the interface, can be + * used to get the interface */ +}; + +/** + * Extra supporting infrastructure passed to the init() function of + * a factory. It can be extra information or interfaces such as logging. + */ +struct spa_support { + const char *type; /*< the type of the support item */ + void *data; /*< specific data for the item */ +}; + +/** Find a support item of the given type */ +static inline void *spa_support_find(const struct spa_support *support, + uint32_t n_support, + const char *type) +{ + uint32_t i; + for (i = 0; i < n_support; i++) { + if (strcmp(support[i].type, type) == 0) + return support[i].data; + } + return NULL; +} + +#define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) } + +struct spa_handle_factory { + /** The version of this structure */ +#define SPA_VERSION_HANDLE_FACTORY 1 + uint32_t version; + /** + * The name of the factory contains a logical name that describes + * the function of the handle. Other plugins might contain an alternative + * implementation with the same name. + * + * See utils/names.h for the list of standard names. + * + * Examples include: + * + * api.alsa.pcm.sink: an object to write PCM samples to an alsa PLAYBACK + * device + * api.v4l2.source: an object to read from a v4l2 source. + */ + const char *name; + /** + * Extra information about the handles of this factory. + */ + const struct spa_dict *info; + /** + * Get the size of handles from this factory. + * + * \param factory a spa_handle_factory + * \param params extra parameters that determine the size of the + * handle. + */ + size_t (*get_size) (const struct spa_handle_factory *factory, + const struct spa_dict *params); + + /** + * Initialize an instance of this factory. The caller should allocate + * memory at least size bytes and pass this as \a handle. + * + * \a support can optionally contain extra interfaces or data items that the + * plugin can use such as a logger. + * + * \param factory a spa_handle_factory + * \param handle a pointer to memory + * \param info extra handle specific information, usually obtained + * from a spa_device. This can be used to configure the handle. + * \param support support items + * \param n_support number of elements in \a support + * \return 0 on success + * < 0 errno type error + */ + int (*init) (const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support); + + /** + * spa_handle_factory::enum_interface_info: + * \param factory: a #spa_handle_factory + * \param info: result to hold spa_interface_info. + * \param index: index to keep track of the enumeration, 0 for first item + * + * Enumerate the interface information for \a factory. + * + * \return 1 when an item is available + * 0 when no more items are available + * < 0 errno type error + */ + int (*enum_interface_info) (const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t *index); +}; + +#define spa_handle_factory_get_size(h,...) (h)->get_size((h),__VA_ARGS__) +#define spa_handle_factory_init(h,...) (h)->init((h),__VA_ARGS__) +#define spa_handle_factory_enum_interface_info(h,...) (h)->enum_interface_info((h),__VA_ARGS__) + +/** + * The function signature of the entry point in a plugin. + * + * \param factory a location to hold the factory result + * \param index index to keep track of the enumeration + * \return 1 on success + * 0 when there are no more factories + * -EINVAL when factory is NULL + */ +typedef int (*spa_handle_factory_enum_func_t) (const struct spa_handle_factory **factory, + uint32_t *index); + +#define SPA_HANDLE_FACTORY_ENUM_FUNC_NAME "spa_handle_factory_enum" + +/** + * The entry point in a plugin. + * + * \param factory a location to hold the factory result + * \param index index to keep track of the enumeration + * \return 1 on success + * 0 when no more items are available + * < 0 errno type error + */ +int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index); + + + +#define SPA_KEY_FACTORY_NAME "factory.name" /**< the name of a factory */ +#define SPA_KEY_FACTORY_AUTHOR "factory.author" /**< a comma separated list of factory authors */ +#define SPA_KEY_FACTORY_DESCRIPTION "factory.description" /**< description of a factory */ +#define SPA_KEY_FACTORY_USAGE "factory.usage" /**< usage of a factory */ + +#define SPA_KEY_LIBRARY_NAME "library.name" /**< the name of a library. This is usually + * the filename of the plugin without the + * path or the plugin extension. */ + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PLUGIN_H */ diff --git a/third_party/pipewire/spa/support/system.h b/third_party/pipewire/spa/support/system.h new file mode 100644 index 0000000000..8076ceb4bb --- /dev/null +++ b/third_party/pipewire/spa/support/system.h @@ -0,0 +1,165 @@ +/* Simple Plugin API + * + * Copyright © 2019 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_SYSTEM_H +#define SPA_SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct itimerspec; + +#include <time.h> +#include <sys/types.h> + +#include <spa/utils/defs.h> +#include <spa/utils/hook.h> + +/** \defgroup spa_system System + * I/O, clock, polling, timer, and signal interfaces + */ + +/** + * \addtogroup spa_system + * \{ + */ + +/** + * a collection of core system functions + */ +#define SPA_TYPE_INTERFACE_System SPA_TYPE_INFO_INTERFACE_BASE "System" +#define SPA_TYPE_INTERFACE_DataSystem SPA_TYPE_INFO_INTERFACE_BASE "DataSystem" + +#define SPA_VERSION_SYSTEM 0 +struct spa_system { struct spa_interface iface; }; + +/* IO events */ +#define SPA_IO_IN (1 << 0) +#define SPA_IO_OUT (1 << 2) +#define SPA_IO_ERR (1 << 3) +#define SPA_IO_HUP (1 << 4) + +/* flags */ +#define SPA_FD_CLOEXEC (1<<0) +#define SPA_FD_NONBLOCK (1<<1) +#define SPA_FD_EVENT_SEMAPHORE (1<<2) +#define SPA_FD_TIMER_ABSTIME (1<<3) +#define SPA_FD_TIMER_CANCEL_ON_SET (1<<4) + +struct spa_poll_event { + uint32_t events; + void *data; +}; + +struct spa_system_methods { +#define SPA_VERSION_SYSTEM_METHODS 0 + uint32_t version; + + /* read/write/ioctl */ + ssize_t (*read) (void *object, int fd, void *buf, size_t count); + ssize_t (*write) (void *object, int fd, const void *buf, size_t count); + int (*ioctl) (void *object, int fd, unsigned long request, ...); + int (*close) (void *object, int fd); + + /* clock */ + int (*clock_gettime) (void *object, + int clockid, struct timespec *value); + int (*clock_getres) (void *object, + int clockid, struct timespec *res); + + /* poll */ + int (*pollfd_create) (void *object, int flags); + int (*pollfd_add) (void *object, int pfd, int fd, uint32_t events, void *data); + int (*pollfd_mod) (void *object, int pfd, int fd, uint32_t events, void *data); + int (*pollfd_del) (void *object, int pfd, int fd); + int (*pollfd_wait) (void *object, int pfd, + struct spa_poll_event *ev, int n_ev, int timeout); + + /* timers */ + int (*timerfd_create) (void *object, int clockid, int flags); + int (*timerfd_settime) (void *object, + int fd, int flags, + const struct itimerspec *new_value, + struct itimerspec *old_value); + int (*timerfd_gettime) (void *object, + int fd, struct itimerspec *curr_value); + int (*timerfd_read) (void *object, int fd, uint64_t *expirations); + + /* events */ + int (*eventfd_create) (void *object, int flags); + int (*eventfd_write) (void *object, int fd, uint64_t count); + int (*eventfd_read) (void *object, int fd, uint64_t *count); + + /* signals */ + int (*signalfd_create) (void *object, int signal, int flags); + int (*signalfd_read) (void *object, int fd, int *signal); +}; + +#define spa_system_method_r(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_system *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_system_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) + + +#define spa_system_read(s,...) spa_system_method_r(s,read,0,__VA_ARGS__) +#define spa_system_write(s,...) spa_system_method_r(s,write,0,__VA_ARGS__) +#define spa_system_ioctl(s,...) spa_system_method_r(s,ioctl,0,__VA_ARGS__) +#define spa_system_close(s,...) spa_system_method_r(s,close,0,__VA_ARGS__) + +#define spa_system_clock_gettime(s,...) spa_system_method_r(s,clock_gettime,0,__VA_ARGS__) +#define spa_system_clock_getres(s,...) spa_system_method_r(s,clock_getres,0,__VA_ARGS__) + +#define spa_system_pollfd_create(s,...) spa_system_method_r(s,pollfd_create,0,__VA_ARGS__) +#define spa_system_pollfd_add(s,...) spa_system_method_r(s,pollfd_add,0,__VA_ARGS__) +#define spa_system_pollfd_mod(s,...) spa_system_method_r(s,pollfd_mod,0,__VA_ARGS__) +#define spa_system_pollfd_del(s,...) spa_system_method_r(s,pollfd_del,0,__VA_ARGS__) +#define spa_system_pollfd_wait(s,...) spa_system_method_r(s,pollfd_wait,0,__VA_ARGS__) + +#define spa_system_timerfd_create(s,...) spa_system_method_r(s,timerfd_create,0,__VA_ARGS__) +#define spa_system_timerfd_settime(s,...) spa_system_method_r(s,timerfd_settime,0,__VA_ARGS__) +#define spa_system_timerfd_gettime(s,...) spa_system_method_r(s,timerfd_gettime,0,__VA_ARGS__) +#define spa_system_timerfd_read(s,...) spa_system_method_r(s,timerfd_read,0,__VA_ARGS__) + +#define spa_system_eventfd_create(s,...) spa_system_method_r(s,eventfd_create,0,__VA_ARGS__) +#define spa_system_eventfd_write(s,...) spa_system_method_r(s,eventfd_write,0,__VA_ARGS__) +#define spa_system_eventfd_read(s,...) spa_system_method_r(s,eventfd_read,0,__VA_ARGS__) + +#define spa_system_signalfd_create(s,...) spa_system_method_r(s,signalfd_create,0,__VA_ARGS__) +#define spa_system_signalfd_read(s,...) spa_system_method_r(s,signalfd_read,0,__VA_ARGS__) + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_SYSTEM_H */ diff --git a/third_party/pipewire/spa/support/thread.h b/third_party/pipewire/spa/support/thread.h new file mode 100644 index 0000000000..ef3866f014 --- /dev/null +++ b/third_party/pipewire/spa/support/thread.h @@ -0,0 +1,149 @@ +/* Simple Plugin API + * + * Copyright © 2021 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_THREAD_H +#define SPA_THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> +#include <errno.h> + +#include <spa/utils/defs.h> +#include <spa/utils/hook.h> +#include <spa/utils/dict.h> + +/** \defgroup spa_thread Thread + * Threading utility interfaces + */ + +/** + * \addtogroup spa_thread + * \{ + */ + +/** a thread object. + * This can be cast to a platform native thread, like pthread on posix systems + */ +#define SPA_TYPE_INFO_Thread SPA_TYPE_INFO_POINTER_BASE "Thread" +struct spa_thread; + +#define SPA_TYPE_INTERFACE_ThreadUtils SPA_TYPE_INFO_INTERFACE_BASE "ThreadUtils" +#define SPA_VERSION_THREAD_UTILS 0 +struct spa_thread_utils { struct spa_interface iface; }; + +/** thread utils */ +struct spa_thread_utils_methods { +#define SPA_VERSION_THREAD_UTILS_METHODS 0 + uint32_t version; + + /** create a new thread that runs \a start with \a arg */ + struct spa_thread * (*create) (void *object, const struct spa_dict *props, + void *(*start)(void*), void *arg); + /** stop and join a thread */ + int (*join)(void *object, struct spa_thread *thread, void **retval); + + /** get realtime priority range for threads created with \a props */ + int (*get_rt_range) (void *object, const struct spa_dict *props, int *min, int *max); + /** acquire realtime priority, a priority of -1 refers to the priority + * configured in the realtime module + */ + int (*acquire_rt) (void *object, struct spa_thread *thread, int priority); + /** drop realtime priority */ + int (*drop_rt) (void *object, struct spa_thread *thread); +}; + +/** \copydoc spa_thread_utils_methods.create + * \sa spa_thread_utils_methods.create */ +static inline struct spa_thread *spa_thread_utils_create(struct spa_thread_utils *o, + const struct spa_dict *props, void *(*start_routine)(void*), void *arg) +{ + struct spa_thread *res = NULL; + spa_interface_call_res(&o->iface, + struct spa_thread_utils_methods, res, create, 0, + props, start_routine, arg); + return res; +} + +/** \copydoc spa_thread_utils_methods.join + * \sa spa_thread_utils_methods.join */ +static inline int spa_thread_utils_join(struct spa_thread_utils *o, + struct spa_thread *thread, void **retval) +{ + int res = -ENOTSUP; + spa_interface_call_res(&o->iface, + struct spa_thread_utils_methods, res, join, 0, + thread, retval); + return res; +} + +/** \copydoc spa_thread_utils_methods.get_rt_range + * \sa spa_thread_utils_methods.get_rt_range */ +static inline int spa_thread_utils_get_rt_range(struct spa_thread_utils *o, + const struct spa_dict *props, int *min, int *max) +{ + int res = -ENOTSUP; + spa_interface_call_res(&o->iface, + struct spa_thread_utils_methods, res, get_rt_range, 0, + props, min, max); + return res; +} + +/** \copydoc spa_thread_utils_methods.acquire_rt + * \sa spa_thread_utils_methods.acquire_rt */ +static inline int spa_thread_utils_acquire_rt(struct spa_thread_utils *o, + struct spa_thread *thread, int priority) +{ + int res = -ENOTSUP; + spa_interface_call_res(&o->iface, + struct spa_thread_utils_methods, res, acquire_rt, 0, + thread, priority); + return res; +} + +/** \copydoc spa_thread_utils_methods.drop_rt + * \sa spa_thread_utils_methods.drop_rt */ +static inline int spa_thread_utils_drop_rt(struct spa_thread_utils *o, + struct spa_thread *thread) +{ + int res = -ENOTSUP; + spa_interface_call_res(&o->iface, + struct spa_thread_utils_methods, res, drop_rt, 0, thread); + return res; +} + +#define SPA_KEY_THREAD_NAME "thread.name" /* the thread name */ +#define SPA_KEY_THREAD_STACK_SIZE "thread.stack-size" /* the stack size of the thread */ + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_THREAD_H */ |