mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	docs: more tutorial
This commit is contained in:
		
							parent
							
								
									0ee5feab67
								
							
						
					
					
						commit
						44efab6c31
					
				
					 3 changed files with 122 additions and 6 deletions
				
			
		| 
						 | 
					@ -3,6 +3,6 @@
 | 
				
			||||||
Welcome to the PipeWire tutorial. The goal is to learn to
 | 
					Welcome to the PipeWire tutorial. The goal is to learn to
 | 
				
			||||||
PipeWire API step-by-step with simple short examples.
 | 
					PipeWire API step-by-step with simple short examples.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1) Getting started [tutorial 1](tutorial1.md).
 | 
					1) Getting started ([tutorial 1](tutorial1.md)).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2) Enumerating objects [tutorial 2](tutorial2.md).
 | 
					2) Enumerating objects ([tutorial 2](tutorial2.md)).
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,6 @@
 | 
				
			||||||
# Tutorial 1
 | 
					[index](tutorial-index.md)  [next](tutorial2.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Getting started (Tutorial 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In this tutorial we show the basics of a simple PipeWire application.
 | 
					In this tutorial we show the basics of a simple PipeWire application.
 | 
				
			||||||
Use this tutorial to get started and help you set up your development
 | 
					Use this tutorial to get started and help you set up your development
 | 
				
			||||||
| 
						 | 
					@ -43,3 +45,4 @@ Linked with libpipewire 0.3.5
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[index](tutorial-index.md)  [next](tutorial2.md)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										119
									
								
								doc/tutorial2.md
									
										
									
									
									
								
							
							
						
						
									
										119
									
								
								doc/tutorial2.md
									
										
									
									
									
								
							| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
# Tutorial 2
 | 
					[previous](tutorial1.md) [index](tutorial-index.md)  [next](tutorial3.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Enumerating objects (Tutorial 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In this tutorial we show how to connect to a PipeWire daemon and 
 | 
					In this tutorial we show how to connect to a PipeWire daemon and 
 | 
				
			||||||
enumerate the objects that it has.
 | 
					enumerate the objects that it has.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Initialization
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Let take a look at the following application to start.
 | 
					Let take a look at the following application to start.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```c
 | 
					```c
 | 
				
			||||||
| 
						 | 
					@ -65,3 +65,116 @@ use:
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
gcc -Wall test2.c -o test2 $(pkg-config --cflags --libs libpipewire-0.3)
 | 
					gcc -Wall test2.c -o test2 $(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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```c
 | 
				
			||||||
 | 
						...
 | 
				
			||||||
 | 
					        pw_init(&argc, &argv);
 | 
				
			||||||
 | 
						...
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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, wiating 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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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 */);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```c
 | 
				
			||||||
 | 
					        struct pw_core *core;
 | 
				
			||||||
 | 
					        core = pw_context_connect(context,
 | 
				
			||||||
 | 
					                        NULL /* properties */,
 | 
				
			||||||
 | 
					                        0 /* user_data size */);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now that everything is set up we can start the mainloop and let
 | 
				
			||||||
 | 
					the communication between client and server continue:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```c
 | 
				
			||||||
 | 
					        pw_main_loop_run(loop);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[previous](tutorial1.md) [index](tutorial-index.md)  [next](tutorial3.md)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue