diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:28:17 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:28:17 +0000 |
commit | 7a46c07230b8d8108c0e8e80df4522d0ac116538 (patch) | |
tree | d483300dab478b994fe199a5d19d18d74153718a /doc/tutorial2.dox | |
parent | Initial commit. (diff) | |
download | pipewire-0bfb2679f751193be0325ef92c84c3863d22ac84.tar.xz pipewire-0bfb2679f751193be0325ef92c84c3863d22ac84.zip |
Adding upstream version 0.3.65.upstream/0.3.65upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'doc/tutorial2.dox')
-rw-r--r-- | doc/tutorial2.dox | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/doc/tutorial2.dox b/doc/tutorial2.dox new file mode 100644 index 0000000..1688aed --- /dev/null +++ b/doc/tutorial2.dox @@ -0,0 +1,129 @@ +/** \page page_tutorial2 Tutorial - Part 2: Enumerating Objects + +\ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3 + +In this tutorial we show how to connect to a PipeWire daemon and +enumerate the objects that it has. + +Let take a look at the following application to start. + +\snippet tutorial2.c code + +To compile the simple test application, copy it into a tutorial2.c file and +use: + + gcc -Wall tutorial2.c -o tutorial2 $(pkg-config --cflags --libs libpipewire-0.3) + +Let's break this down: + +First we need to initialize the PipeWire library with `pw_init()` as we +saw in the previous tutorial. This will load and configure the right +modules and setup logging and other tasks. + +\code{.c} + ... + pw_init(&argc, &argv); + ... +\endcode + +Next we need to create one of the `struct pw_loop` wrappers. PipeWire +ships with 2 types of mainloop implementations. We will use the +`struct pw_main_loop` implementation, we will see later how we can +use the `struct pw_thread_loop` implementation as well. + +The mainloop is an abstraction of a big poll loop, waiting for events +to occur and things to do. Most of the PipeWire work will actually +be performed in the context of this loop and so we need to make one +first. + +We then need to make a new context object with the loop. This context +object will manage the resources for us and will make it possible for +us to connect to a PipeWire daemon: + +\code{.c} + struct pw_main_loop *loop; + struct pw_context *context; + + loop = pw_main_loop_new(NULL /* properties */); + context = pw_context_new(pw_main_loop_get_loop(loop), + NULL /* properties */, + 0 /* user_data size */); +\endcode + +It is possible to give extra properties when making the mainloop or +context to tweak its features and functionality. It is also possible +to add extra data to the allocated objects for your user data. It will +stay alive for as long as the object is alive. We will use this +feature later. + +A real implementation would also need to check if the allocation +succeeded and do some error handling, but we leave that out to make +the code easier to read. + +With the context we can now connect to the PipeWire daemon: + +\code{.c} + struct pw_core *core; + core = pw_context_connect(context, + NULL /* properties */, + 0 /* user_data size */); +\endcode + +This creates a socket between the client and the server and makes +a proxy object (with ID 0) for the core. Don't forget to check the +result here, a NULL value means that the connection failed. + +At this point we can send messages to the server and receive events. +For now we're not going to handle events on this core proxy but +we're going to handle them on the registry object. + + +\code{.c} + struct pw_registry *registry; + struct spa_hook registry_listener; + + registry = pw_core_get_registry(core, PW_VERSION_REGISTRY, + 0 /* user_data size */); + + spa_zero(registry_listener); + pw_registry_add_listener(registry, ®istry_listener, + ®istry_events, NULL); +\endcode + +From the core we get the registry proxy object and when we use +`pw_registry_add_listener()` to listen for events. We need a +small `struct spa_hook` to keep track of the listener and a +reference to the `struct pw_registry_events` that contains the +events we want to listen to. + +This is how we define the event handler and the function to +handle the events: + +\code{.c} +static const struct pw_registry_events registry_events = { + PW_VERSION_REGISTRY_EVENTS, + .global = registry_event_global, +}; + +static void registry_event_global(void *data, uint32_t id, + uint32_t permissions, const char *type, uint32_t version, + const struct spa_dict *props) +{ + printf("object: id:%u type:%s/%d\n", id, type, version); +} +\endcode + +Now that everything is set up we can start the mainloop and let +the communication between client and server continue: + +\code{.c} + pw_main_loop_run(loop); +\endcode + +Since we don't call `pw_main_loop_quit()` anywhere, this loop will +continue forever. In the next tutorial we'll see how we can nicely +exit our application after we received all server objects. + +\ref page_tutorial1 | \ref page_tutorial "Index" | \ref page_tutorial3 + +*/ |