mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-30 13:14:16 -04:00
filter-graph: add support for multiple handles
Make instantiate create all the related handles in one go. When a processing node has 1 in/out, multiple handles are created to support multichannel. By instantiating the handles in one go, the implementation could do some special multichannel support or do some optimizations, like parse the config string only once.
This commit is contained in:
parent
b3eb2eabb8
commit
aa075c2a12
9 changed files with 175 additions and 59 deletions
|
|
@ -63,7 +63,7 @@ struct spa_fga_descriptor {
|
|||
struct spa_fga_port *ports;
|
||||
|
||||
int (*instantiate) (const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, int index, const char *config, void **hndl);
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[]);
|
||||
|
||||
void (*cleanup) (void *instance);
|
||||
|
||||
|
|
|
|||
|
|
@ -1682,14 +1682,12 @@ static int impl_activate(void *object, const struct spa_dict *props)
|
|||
d = desc->desc;
|
||||
p = desc->plugin->plugin;
|
||||
|
||||
for (i = 0; i < node->n_hndl; i++) {
|
||||
spa_log_info(impl->log, "instantiate %s %s[%d] rate:%lu", d->name, node->name, i, impl->rate);
|
||||
errno = EINVAL;
|
||||
if ((res = d->instantiate(p, d, impl->rate, i, node->config, &node->hndl[i])) < 0) {
|
||||
spa_log_error(impl->log, "cannot create plugin instance %d rate:%lu: %s",
|
||||
i, impl->rate, spa_strerror(res));
|
||||
goto error;
|
||||
}
|
||||
spa_log_info(impl->log, "instantiate %s %s[%d] rate:%lu", d->name, node->name,
|
||||
node->n_hndl, impl->rate);
|
||||
if ((res = d->instantiate(p, d, impl->rate, node->config, node->n_hndl, node->hndl)) < 0) {
|
||||
spa_log_error(impl->log, "cannot create plugin instance %d rate:%lu: %s",
|
||||
node->n_hndl, impl->rate, spa_strerror(res));
|
||||
goto error;
|
||||
}
|
||||
node->control_changed = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,22 +69,39 @@ struct builtin {
|
|||
float hold;
|
||||
};
|
||||
|
||||
static int builtin_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int instantiate_helper(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[],
|
||||
int (*instantiate1_func) (const struct spa_fga_plugin *plugin,
|
||||
const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl))
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = instantiate1_func(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int builtin_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct builtin *impl;
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
return -errno;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
struct builtin *impl;
|
||||
|
||||
impl->plugin = pl;
|
||||
impl->rate = rate;
|
||||
impl->dsp = impl->plugin->dsp;
|
||||
impl->log = impl->plugin->log;
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
return -errno;
|
||||
|
||||
*hndl = impl;
|
||||
impl->plugin = pl;
|
||||
impl->rate = rate;
|
||||
impl->dsp = impl->plugin->dsp;
|
||||
impl->log = impl->plugin->log;
|
||||
|
||||
hndl[i] = impl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -336,8 +353,8 @@ static void bq_raw_update(struct builtin *impl, float b0, float b1, float b2,
|
|||
* ]
|
||||
* }
|
||||
*/
|
||||
static int bq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int bq_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct builtin *impl;
|
||||
|
|
@ -448,6 +465,12 @@ error:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int bq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, bq_instantiate1);
|
||||
}
|
||||
|
||||
#define BQ_NUM_PORTS 11
|
||||
static struct spa_fga_port bq_ports[] = {
|
||||
{ .index = 0,
|
||||
|
|
@ -1140,8 +1163,8 @@ error:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int convolver_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int convolver_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct convolver_impl *impl = NULL;
|
||||
|
|
@ -1225,6 +1248,12 @@ error_errno:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int convolver_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, convolver_instantiate1);
|
||||
}
|
||||
|
||||
static void convolver_connect_port(void * Instance, unsigned long Port,
|
||||
void * DataLocation)
|
||||
{
|
||||
|
|
@ -1294,8 +1323,8 @@ static const struct spa_fga_descriptor convolve_desc = {
|
|||
};
|
||||
|
||||
/** convolver2 */
|
||||
static int convolver2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int convolver2_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct convolver_impl *impl = NULL;
|
||||
|
|
@ -1403,6 +1432,12 @@ error:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int convolver2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, convolver2_instantiate1);
|
||||
}
|
||||
|
||||
static void convolver2_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
struct convolver_impl *impl = Instance;
|
||||
|
|
@ -1504,8 +1539,8 @@ static void delay_cleanup(void * Instance)
|
|||
free(impl);
|
||||
}
|
||||
|
||||
static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int delay_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct delay_impl *impl;
|
||||
|
|
@ -1573,6 +1608,12 @@ static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct s
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int delay_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, delay_instantiate1);
|
||||
}
|
||||
|
||||
static void delay_connect_port(void * Instance, unsigned long Port,
|
||||
void * DataLocation)
|
||||
{
|
||||
|
|
@ -2302,8 +2343,8 @@ static int parse_filters(struct plugin *pl, struct spa_json *iter, int rate,
|
|||
* filtersX = [ ... ] # to load channel X
|
||||
* }
|
||||
*/
|
||||
static int param_eq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int param_eq_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct spa_json it[3];
|
||||
|
|
@ -2387,6 +2428,12 @@ error:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int param_eq_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, param_eq_instantiate1);
|
||||
}
|
||||
|
||||
static void param_eq_connect_port(void * Instance, unsigned long Port,
|
||||
void * DataLocation)
|
||||
{
|
||||
|
|
@ -2666,8 +2713,8 @@ struct dcblock_impl {
|
|||
struct dcblock dc[8];
|
||||
};
|
||||
|
||||
static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int dcblock_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct dcblock_impl *impl;
|
||||
|
|
@ -2684,6 +2731,12 @@ static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dcblock_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, dcblock_instantiate1);
|
||||
}
|
||||
|
||||
static void dcblock_run_n(struct dcblock dc[], float *dst[], const float *src[],
|
||||
uint32_t n_src, float R, uint32_t n_samples)
|
||||
{
|
||||
|
|
@ -3267,8 +3320,8 @@ struct busy_impl {
|
|||
float cpu_scale;
|
||||
};
|
||||
|
||||
static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int busy_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct busy_impl *impl;
|
||||
|
|
@ -3320,6 +3373,12 @@ static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct sp
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int busy_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
return instantiate_helper(plugin, desc, rate, config, n_hndl, hndl, busy_instantiate1);
|
||||
}
|
||||
|
||||
static void busy_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
struct busy_impl *impl = Instance;
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ struct ebur128_impl {
|
|||
ebur128_state *st[7];
|
||||
};
|
||||
|
||||
static int ebur128_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int ebur128_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct ebur128_impl *impl;
|
||||
|
|
@ -129,6 +129,17 @@ error:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ebur128_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = ebur128_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ebur128_run(void * Instance, unsigned long SampleCount)
|
||||
{
|
||||
struct ebur128_impl *impl = Instance;
|
||||
|
|
@ -418,21 +429,24 @@ struct lufs2gain_impl {
|
|||
float *port[3];
|
||||
};
|
||||
|
||||
static int lufs2gain_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int lufs2gain_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct lufs2gain_impl *impl;
|
||||
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
return -errno;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
struct lufs2gain_impl *impl;
|
||||
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
impl->rate = rate;
|
||||
*hndl = impl;
|
||||
impl = calloc(1, sizeof(*impl));
|
||||
if (impl == NULL)
|
||||
return -errno;
|
||||
|
||||
impl->plugin = pl;
|
||||
impl->dsp = pl->dsp;
|
||||
impl->log = pl->log;
|
||||
impl->rate = rate;
|
||||
hndl[i] = impl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ static void ffmpeg_cleanup(void *instance)
|
|||
free(i);
|
||||
}
|
||||
|
||||
static int ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int ffmpeg_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct descriptor *d = (struct descriptor *)desc;
|
||||
struct plugin *p = d->p;
|
||||
|
|
@ -186,6 +186,17 @@ error_free:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int ffmpeg_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = ffmpeg_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ffmpeg_free(const struct spa_fga_descriptor *desc)
|
||||
{
|
||||
struct descriptor *d = (struct descriptor*)desc;
|
||||
|
|
|
|||
|
|
@ -35,12 +35,13 @@ struct descriptor {
|
|||
};
|
||||
|
||||
static int ladspa_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void **hndl)
|
||||
{
|
||||
struct descriptor *d = (struct descriptor *)desc;
|
||||
*hndl = d->d->instantiate(d->d, rate);
|
||||
if (*hndl == NULL)
|
||||
return -ENOMEM;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((hndl[i] = d->d->instantiate(d->d, rate)) == NULL)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -374,8 +374,8 @@ static int log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int lv2_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct descriptor *d = (struct descriptor*)desc;
|
||||
struct plugin *p = d->p;
|
||||
|
|
@ -465,6 +465,17 @@ static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lv2_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = lv2_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lv2_cleanup(void *instance)
|
||||
{
|
||||
struct instance *i = instance;
|
||||
|
|
|
|||
|
|
@ -272,8 +272,8 @@ static int set_value(void *data, enum ONNXTensorElementDataType type, double val
|
|||
* }
|
||||
*/
|
||||
|
||||
static int onnx_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int onnx_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct descriptor *d = (struct descriptor *)desc;
|
||||
struct plugin *p = d->p;
|
||||
|
|
@ -324,6 +324,17 @@ error:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int onnx_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = onnx_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void onnx_cleanup(void *instance)
|
||||
{
|
||||
struct instance *i = instance;
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ struct spatializer_impl {
|
|||
struct convolver *conv[3];
|
||||
};
|
||||
|
||||
static int spatializer_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, int index, const char *config, void **hndl)
|
||||
static int spatializer_instantiate1(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor * Descriptor,
|
||||
uint32_t rate, uint32_t index, const char *config, void **hndl)
|
||||
{
|
||||
struct plugin *pl = SPA_CONTAINER_OF(plugin, struct plugin, plugin);
|
||||
struct spatializer_impl *impl;
|
||||
|
|
@ -234,6 +234,17 @@ error:
|
|||
return res;
|
||||
}
|
||||
|
||||
static int spatializer_instantiate(const struct spa_fga_plugin *plugin, const struct spa_fga_descriptor *desc,
|
||||
uint32_t rate, const char *config, uint32_t n_hndl, void *hndl[])
|
||||
{
|
||||
int res;
|
||||
for (uint32_t i = 0; i < n_hndl; i++) {
|
||||
if ((res = spatializer_instantiate1(plugin, desc, rate, i, config, &hndl[i])) < 0)
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data,
|
||||
size_t size, void *user_data)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue