1 /* Simple Plugin API
2 *
3 * Copyright © 2019 Wim Taymans
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #ifndef SPA_NODE_UTILS_H
26 #define SPA_NODE_UTILS_H
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #include <spa/pod/builder.h>
33
34 #include <spa/node/node.h>
35
36 struct spa_result_node_params_data {
37 struct spa_pod_builder *builder;
38 struct spa_result_node_params data;
39 };
40
spa_result_func_node_params(void * data,int seq,int res,uint32_t type,const void * result)41 static inline void spa_result_func_node_params(void *data,
42 int seq, int res, uint32_t type, const void *result)
43 {
44 struct spa_result_node_params_data *d =
45 (struct spa_result_node_params_data *) data;
46 const struct spa_result_node_params *r =
47 (const struct spa_result_node_params *) result;
48 uint32_t offset = d->builder->state.offset;
49 spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param));
50 d->data.next = r->next;
51 d->data.param = SPA_MEMBER(d->builder->data, offset, struct spa_pod);
52 }
53
spa_node_enum_params_sync(struct spa_node * node,uint32_t id,uint32_t * index,const struct spa_pod * filter,struct spa_pod ** param,struct spa_pod_builder * builder)54 static inline int spa_node_enum_params_sync(struct spa_node *node,
55 uint32_t id, uint32_t *index,
56 const struct spa_pod *filter,
57 struct spa_pod **param,
58 struct spa_pod_builder *builder)
59 {
60 struct spa_result_node_params_data data = { builder, };
61 struct spa_hook listener = { 0 };
62 static const struct spa_node_events node_events = {
63 SPA_VERSION_NODE_EVENTS,
64 .result = spa_result_func_node_params,
65 };
66 int res;
67
68 res = spa_node_add_listener(node, &listener, &node_events, &data);
69 if (res >= 0) {
70 res = spa_node_enum_params(node, 0, id, *index, 1, filter);
71 spa_hook_remove(&listener);
72 }
73
74 if (data.data.param == NULL) {
75 if (res > 0)
76 res = 0;
77 } else {
78 *index = data.data.next;
79 *param = data.data.param;
80 res = 1;
81 }
82 return res;
83 }
84
spa_node_port_enum_params_sync(struct spa_node * node,enum spa_direction direction,uint32_t port_id,uint32_t id,uint32_t * index,const struct spa_pod * filter,struct spa_pod ** param,struct spa_pod_builder * builder)85 static inline int spa_node_port_enum_params_sync(struct spa_node *node,
86 enum spa_direction direction, uint32_t port_id,
87 uint32_t id, uint32_t *index,
88 const struct spa_pod *filter,
89 struct spa_pod **param,
90 struct spa_pod_builder *builder)
91 {
92 struct spa_result_node_params_data data = { builder, };
93 struct spa_hook listener = { 0 };
94 static const struct spa_node_events node_events = {
95 SPA_VERSION_NODE_EVENTS,
96 .result = spa_result_func_node_params,
97 };
98 int res;
99
100 res = spa_node_add_listener(node, &listener, &node_events, &data);
101 if (res >= 0) {
102 res = spa_node_port_enum_params(node, 0, direction, port_id,
103 id, *index, 1, filter);
104 spa_hook_remove(&listener);
105 }
106
107 if (data.data.param == NULL) {
108 if (res > 0)
109 res = 0;
110 } else {
111 *index = data.data.next;
112 *param = data.data.param;
113 res = 1;
114 }
115 return res;
116 }
117
118 #define spa_node_emit(hooks,method,version,...) \
119 spa_hook_list_call_simple(hooks, struct spa_node_events, \
120 method, version, ##__VA_ARGS__)
121
122 #define spa_node_emit_info(hooks,...) spa_node_emit(hooks,info, 0, __VA_ARGS__)
123 #define spa_node_emit_port_info(hooks,...) spa_node_emit(hooks,port_info, 0, __VA_ARGS__)
124 #define spa_node_emit_result(hooks,...) spa_node_emit(hooks,result, 0, __VA_ARGS__)
125 #define spa_node_emit_event(hooks,...) spa_node_emit(hooks,event, 0, __VA_ARGS__)
126
127
128 #define spa_node_call(callbacks,method,version,...) \
129 ({ \
130 int _res = -ENOTSUP; \
131 spa_callbacks_call_res(callbacks, struct spa_node_callbacks, \
132 _res, method, version, ##__VA_ARGS__); \
133 _res; \
134 })
135
136 #define spa_node_call_ready(hook,...) spa_node_call(hook, ready, 0, __VA_ARGS__)
137 #define spa_node_call_reuse_buffer(hook,...) spa_node_call(hook, reuse_buffer, 0, __VA_ARGS__)
138 #define spa_node_call_xrun(hook,...) spa_node_call(hook, xrun, 0, __VA_ARGS__)
139
140 #ifdef __cplusplus
141 } /* extern "C" */
142 #endif
143
144 #endif /* SPA_NODE_UTILS_H */
145