1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include <glib.h>
9 #include "mozilla/Types.h"
10 #include "prlink.h"
11
12 #include <pipewire/pipewire.h>
13
14 #define GET_FUNC(func, lib) \
15 func##_fn = \
16 (decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \
17
18 #define IS_FUNC_LOADED(func) \
19 (func != nullptr) \
20
21 struct GUnixFDList;
22
23 extern "C" gint
g_unix_fd_list_get(struct GUnixFDList * list,gint index_,GError ** error)24 g_unix_fd_list_get(struct GUnixFDList *list,
25 gint index_,
26 GError **error)
27 {
28 static PRLibrary* gioLib = nullptr;
29 static bool gioInitialized = false;
30 static gint (*g_unix_fd_list_get_fn)(struct GUnixFDList *list,
31 gint index_, GError **error) = nullptr;
32
33 if (!gioInitialized) {
34 gioInitialized = true;
35 gioLib = PR_LoadLibrary("libgio-2.0.so.0");
36 if (!gioLib) {
37 return -1;
38 }
39 GET_FUNC(g_unix_fd_list_get, gioLib);
40 }
41
42 if (!g_unix_fd_list_get_fn) {
43 return -1;
44 }
45
46 return g_unix_fd_list_get_fn(list, index_, error);
47 }
48
49 static struct pw_core * (*pw_context_connect_fn)(struct pw_context *context,
50 struct pw_properties *properties,
51 size_t user_data_size);
52 static struct pw_core * (*pw_context_connect_fd_fn)(struct pw_context *context,
53 int fd,
54 struct pw_properties *properties,
55 size_t user_data_size);
56 static void (*pw_context_destroy_fn)(struct pw_context *context);
57 struct pw_context * (*pw_context_new_fn)(struct pw_loop *main_loop,
58 struct pw_properties *props,
59 size_t user_data_size);
60 static int (*pw_core_disconnect_fn)(struct pw_core *core);
61 static void (*pipewire_init_fn)(int *argc, char **argv[]);
62 static void (*pw_stream_add_listener_fn)(struct pw_stream *stream,
63 struct spa_hook *listener,
64 const struct pw_stream_events *events,
65 void *data);
66 static int (*pw_stream_connect_fn)(struct pw_stream *stream,
67 enum pw_direction direction,
68 uint32_t target_id,
69 enum pw_stream_flags flags,
70 const struct spa_pod **params,
71 uint32_t n_params);
72 static struct pw_buffer* (*pw_stream_dequeue_buffer_fn)(struct pw_stream *stream);
73 static void (*pw_stream_destroy_fn)(struct pw_stream *stream);
74 static struct pw_stream* (*pw_stream_new_fn)(struct pw_core *core,
75 const char *name,
76 struct pw_properties *props);
77 static int (*pw_stream_queue_buffer_fn)(struct pw_stream *stream,
78 struct pw_buffer *buffer);
79 static int (*pw_stream_update_params_fn)(struct pw_stream *stream,
80 const struct spa_pod **params,
81 uint32_t n_params);
82 static void (*pw_thread_loop_destroy_fn)(struct pw_thread_loop *loop);
83 static struct pw_loop* (*pw_thread_loop_get_loop_fn)(struct pw_thread_loop *loop);
84 static struct pw_thread_loop* (*pw_thread_loop_new_fn)(const char *name,
85 const struct spa_dict *props);
86 static int (*pw_thread_loop_start_fn)(struct pw_thread_loop *loop);
87 static void (*pw_thread_loop_stop_fn)(struct pw_thread_loop *loop);
88
IsPwLibraryLoaded()89 bool IsPwLibraryLoaded() {
90 static bool isLoaded =
91 (IS_FUNC_LOADED(pw_context_connect_fn) &&
92 IS_FUNC_LOADED(pw_context_connect_fd_fn) &&
93 IS_FUNC_LOADED(pw_context_destroy_fn) &&
94 IS_FUNC_LOADED(pw_context_new_fn) &&
95 IS_FUNC_LOADED(pw_core_disconnect_fn) &&
96 IS_FUNC_LOADED(pipewire_init_fn) &&
97 IS_FUNC_LOADED(pw_stream_add_listener_fn) &&
98 IS_FUNC_LOADED(pw_stream_connect_fn) &&
99 IS_FUNC_LOADED(pw_stream_dequeue_buffer_fn) &&
100 IS_FUNC_LOADED(pw_stream_destroy_fn) &&
101 IS_FUNC_LOADED(pw_stream_new_fn) &&
102 IS_FUNC_LOADED(pw_stream_queue_buffer_fn) &&
103 IS_FUNC_LOADED(pw_stream_update_params_fn) &&
104 IS_FUNC_LOADED(pw_thread_loop_destroy_fn) &&
105 IS_FUNC_LOADED(pw_thread_loop_get_loop_fn) &&
106 IS_FUNC_LOADED(pw_thread_loop_new_fn) &&
107 IS_FUNC_LOADED(pw_thread_loop_start_fn) &&
108 IS_FUNC_LOADED(pw_thread_loop_stop_fn));
109
110 return isLoaded;
111 }
112
LoadPWLibrary()113 bool LoadPWLibrary() {
114 static PRLibrary* pwLib = nullptr;
115 static bool pwInitialized = false;
116
117 //TODO Thread safe
118 if (!pwInitialized) {
119 pwInitialized = true;
120 pwLib = PR_LoadLibrary("libpipewire-0.3.so.0");
121 if (!pwLib) {
122 return false;
123 }
124
125 GET_FUNC(pw_context_connect, pwLib);
126 GET_FUNC(pw_context_connect_fd, pwLib);
127 GET_FUNC(pw_context_destroy, pwLib);
128 GET_FUNC(pw_context_new, pwLib);
129 GET_FUNC(pw_core_disconnect, pwLib);
130 GET_FUNC(pipewire_init, pwLib);
131 GET_FUNC(pw_stream_add_listener, pwLib);
132 GET_FUNC(pw_stream_connect, pwLib);
133 GET_FUNC(pw_stream_dequeue_buffer, pwLib);
134 GET_FUNC(pw_stream_destroy, pwLib);
135 GET_FUNC(pw_stream_new, pwLib);
136 GET_FUNC(pw_stream_queue_buffer, pwLib);
137 GET_FUNC(pw_stream_update_params, pwLib);
138 GET_FUNC(pw_thread_loop_destroy, pwLib);
139 GET_FUNC(pw_thread_loop_get_loop, pwLib);
140 GET_FUNC(pw_thread_loop_new, pwLib);
141 GET_FUNC(pw_thread_loop_start, pwLib);
142 GET_FUNC(pw_thread_loop_stop, pwLib);
143 }
144
145 return IsPwLibraryLoaded();
146 }
147
148 struct pw_core *
pw_context_connect(struct pw_context * context,struct pw_properties * properties,size_t user_data_size)149 pw_context_connect(struct pw_context *context,
150 struct pw_properties *properties,
151 size_t user_data_size)
152 {
153 if (!LoadPWLibrary()) {
154 return nullptr;
155 }
156 return pw_context_connect_fn(context, properties, user_data_size);
157 }
158
159 struct pw_core *
pw_context_connect_fd(struct pw_context * context,int fd,struct pw_properties * properties,size_t user_data_size)160 pw_context_connect_fd(struct pw_context *context,
161 int fd,
162 struct pw_properties *properties,
163 size_t user_data_size)
164 {
165 if (!LoadPWLibrary()) {
166 return nullptr;
167 }
168 return pw_context_connect_fd_fn(context, fd, properties, user_data_size);
169 }
170
171 void
pw_context_destroy(struct pw_context * context)172 pw_context_destroy(struct pw_context *context)
173 {
174 if (!LoadPWLibrary()) {
175 return;
176 }
177 pw_context_destroy_fn(context);
178 }
179
180 struct pw_context *
pw_context_new(struct pw_loop * main_loop,struct pw_properties * props,size_t user_data_size)181 pw_context_new(struct pw_loop *main_loop,
182 struct pw_properties *props,
183 size_t user_data_size)
184 {
185 if (!LoadPWLibrary()) {
186 return nullptr;
187 }
188 return pw_context_new_fn(main_loop, props, user_data_size);
189 }
190
191 int
pw_core_disconnect(struct pw_core * core)192 pw_core_disconnect(struct pw_core *core)
193 {
194 if (!LoadPWLibrary()) {
195 return 0;
196 }
197 return pw_core_disconnect_fn(core);
198 }
199
200 void
pipewire_init(int * argc,char ** argv[])201 pipewire_init(int *argc, char **argv[])
202 {
203 if (!LoadPWLibrary()) {
204 return;
205 }
206 return pipewire_init_fn(argc, argv);
207 }
208
209 void
pw_stream_add_listener(struct pw_stream * stream,struct spa_hook * listener,const struct pw_stream_events * events,void * data)210 pw_stream_add_listener(struct pw_stream *stream,
211 struct spa_hook *listener,
212 const struct pw_stream_events *events,
213 void *data)
214 {
215 if (!LoadPWLibrary()) {
216 return;
217 }
218 return pw_stream_add_listener_fn(stream, listener, events, data);
219 }
220
221 int
pw_stream_connect(struct pw_stream * stream,enum pw_direction direction,uint32_t target_id,enum pw_stream_flags flags,const struct spa_pod ** params,uint32_t n_params)222 pw_stream_connect(struct pw_stream *stream,
223 enum pw_direction direction,
224 uint32_t target_id,
225 enum pw_stream_flags flags,
226 const struct spa_pod **params,
227 uint32_t n_params)
228 {
229 if (!LoadPWLibrary()) {
230 return 0;
231 }
232 return pw_stream_connect_fn(stream, direction, target_id, flags,
233 params, n_params);
234 }
235
236 struct pw_buffer *
pw_stream_dequeue_buffer(struct pw_stream * stream)237 pw_stream_dequeue_buffer(struct pw_stream *stream)
238 {
239 if (!LoadPWLibrary()) {
240 return nullptr;
241 }
242 return pw_stream_dequeue_buffer_fn(stream);
243 }
244
245 void
pw_stream_destroy(struct pw_stream * stream)246 pw_stream_destroy(struct pw_stream *stream)
247 {
248 if (!LoadPWLibrary()) {
249 return;
250 }
251 return pw_stream_destroy_fn(stream);
252 }
253
254 struct pw_stream *
pw_stream_new(struct pw_core * core,const char * name,struct pw_properties * props)255 pw_stream_new(struct pw_core *core,
256 const char *name,
257 struct pw_properties *props)
258 {
259 if (!LoadPWLibrary()) {
260 return nullptr;
261 }
262 return pw_stream_new_fn(core, name, props);
263 }
264
265 int
pw_stream_queue_buffer(struct pw_stream * stream,struct pw_buffer * buffer)266 pw_stream_queue_buffer(struct pw_stream *stream,
267 struct pw_buffer *buffer)
268 {
269 if (!LoadPWLibrary()) {
270 return 0;
271 }
272 return pw_stream_queue_buffer_fn(stream, buffer);
273 }
274
275 int
pw_stream_update_params(struct pw_stream * stream,const struct spa_pod ** params,uint32_t n_params)276 pw_stream_update_params(struct pw_stream *stream,
277 const struct spa_pod **params,
278 uint32_t n_params)
279 {
280 if (!LoadPWLibrary()) {
281 return 0;
282 }
283 return pw_stream_update_params_fn(stream, params, n_params);
284 }
285
286 void
pw_thread_loop_destroy(struct pw_thread_loop * loop)287 pw_thread_loop_destroy(struct pw_thread_loop *loop)
288 {
289 if (!LoadPWLibrary()) {
290 return;
291 }
292 return pw_thread_loop_destroy_fn(loop);
293 }
294
295 struct pw_loop *
pw_thread_loop_get_loop(struct pw_thread_loop * loop)296 pw_thread_loop_get_loop(struct pw_thread_loop *loop)
297 {
298 if (!LoadPWLibrary()) {
299 return nullptr;
300 }
301 return pw_thread_loop_get_loop_fn(loop);
302 }
303
304 struct pw_thread_loop *
pw_thread_loop_new(const char * name,const struct spa_dict * props)305 pw_thread_loop_new(const char *name,
306 const struct spa_dict *props)
307 {
308 if (!LoadPWLibrary()) {
309 return nullptr;
310 }
311 return pw_thread_loop_new_fn(name, props);
312 }
313
314 int
pw_thread_loop_start(struct pw_thread_loop * loop)315 pw_thread_loop_start(struct pw_thread_loop *loop)
316 {
317 if (!LoadPWLibrary()) {
318 return 0;
319 }
320 return pw_thread_loop_start_fn(loop);
321 }
322
323 void
pw_thread_loop_stop(struct pw_thread_loop * loop)324 pw_thread_loop_stop(struct pw_thread_loop *loop)
325 {
326 if (!LoadPWLibrary()) {
327 return;
328 }
329 return pw_thread_loop_stop_fn(loop);
330 }
331