aboutsummaryrefslogtreecommitdiff
path: root/include/pipewire_audio.h
blob: 68e5356a35b01b330fd77125a88b7f1dd988912c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#ifndef GSR_PIPEWIRE_AUDIO_H
#define GSR_PIPEWIRE_AUDIO_H

#include <pipewire/thread-loop.h>
#include <pipewire/context.h>
#include <pipewire/core.h>
#include <spa/utils/hook.h>

#include <stdbool.h>

typedef enum {
    GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_OUTPUT, /* Application audio */
    GSR_PIPEWIRE_AUDIO_NODE_TYPE_STREAM_INPUT,  /* Audio recording input */
    GSR_PIPEWIRE_AUDIO_NODE_TYPE_SINK_OR_SOURCE /* Audio output or input device or combined (virtual) sink */
} gsr_pipewire_audio_node_type;

typedef struct {
    uint32_t id;
    char *name;
    gsr_pipewire_audio_node_type type;
} gsr_pipewire_audio_node;

typedef enum {
    GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_INPUT,
    GSR_PIPEWIRE_AUDIO_PORT_DIRECTION_OUTPUT
} gsr_pipewire_audio_port_direction;

typedef struct {
    uint32_t id;
    uint32_t node_id;
    gsr_pipewire_audio_port_direction direction;
    char *name;
} gsr_pipewire_audio_port;

typedef struct {
    uint32_t id;
    uint32_t output_node_id;
    uint32_t input_node_id;
} gsr_pipewire_audio_link;

typedef enum {
    GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_STREAM, /* Application */
    GSR_PIPEWIRE_AUDIO_LINK_INPUT_TYPE_SINK    /* Combined (virtual) sink */
} gsr_pipewire_audio_link_input_type;

typedef enum {
    GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_STANDARD,
    GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_OUTPUT,
    GSR_PIPEWIRE_AUDIO_REQUESTED_TYPE_DEFAULT_INPUT
} gsr_pipewire_audio_requested_type;

typedef struct {
    char *name;
    gsr_pipewire_audio_requested_type type;
} gsr_pipewire_audio_requested_output;

typedef struct {
    gsr_pipewire_audio_requested_output *outputs;
    int num_outputs;
    char *input_name;
    bool inverted;
    gsr_pipewire_audio_node_type output_type;
    gsr_pipewire_audio_link_input_type input_type;
} gsr_pipewire_audio_requested_link;

typedef struct {
    struct pw_thread_loop *thread_loop;
    struct pw_context *context;
    struct pw_core *core;
    struct spa_hook core_listener;
    struct pw_registry *registry;
    struct spa_hook registry_listener;
    int server_version_sync;

    struct pw_proxy *metadata_proxy;
    struct spa_hook metadata_listener;
    struct spa_hook metadata_proxy_listener;
    char default_output_device_name[128];
    char default_input_device_name[128];

    gsr_pipewire_audio_node *stream_nodes;
    size_t num_stream_nodes;
    size_t stream_nodes_capacity_items;

    gsr_pipewire_audio_port *ports;
    size_t num_ports;
    size_t ports_capacity_items;

    gsr_pipewire_audio_link *links;
    size_t num_links;
    size_t links_capacity_items;

    gsr_pipewire_audio_requested_link *requested_links;
    size_t num_requested_links;
    size_t requested_links_capacity_items;

    struct pw_proxy **virtual_sink_proxies;
    size_t num_virtual_sink_proxies;
    size_t virtual_sink_proxies_capacity_items;
} gsr_pipewire_audio;

bool gsr_pipewire_audio_init(gsr_pipewire_audio *self);
void gsr_pipewire_audio_deinit(gsr_pipewire_audio *self);

bool gsr_pipewire_audio_create_virtual_sink(gsr_pipewire_audio *self, const char *name);

/*
    This function links audio source outputs from applications that match the name |app_names| to the input
    that matches the name |stream_name_input|.
    If an application or a new application starts outputting audio after this function is called and the app name matches
    then it will automatically link the audio sources.
    |app_names| and |stream_name_input| are case-insensitive matches.
*/
bool gsr_pipewire_audio_add_link_from_apps_to_stream(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input);
/*
    This function links audio source outputs from all applications except the ones that match the name |app_names| to the input
    that matches the name |stream_name_input|.
    If an application or a new application starts outputting audio after this function is called and the app name doesn't match
    then it will automatically link the audio sources.
    |app_names| and |stream_name_input| are case-insensitive matches.
*/
bool gsr_pipewire_audio_add_link_from_apps_to_stream_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *stream_name_input);

/*
    This function links audio source outputs from applications that match the name |app_names| to the input
    that matches the name |sink_name_input|.
    If an application or a new application starts outputting audio after this function is called and the app name matches
    then it will automatically link the audio sources.
    |app_names| and |sink_name_input| are case-insensitive matches.
*/
bool gsr_pipewire_audio_add_link_from_apps_to_sink(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input);
/*
    This function links audio source outputs from all applications except the ones that match the name |app_names| to the input
    that matches the name |sink_name_input|.
    If an application or a new application starts outputting audio after this function is called and the app name doesn't match
    then it will automatically link the audio sources.
    |app_names| and |sink_name_input| are case-insensitive matches.
*/
bool gsr_pipewire_audio_add_link_from_apps_to_sink_inverted(gsr_pipewire_audio *self, const char **app_names, int num_app_names, const char *sink_name_input);

/*
    This function links audio source outputs from devices that match the name |source_names| to the input
    that matches the name |sink_name_input|.
    If a device or a new device starts outputting audio after this function is called and the device name matches
    then it will automatically link the audio sources.
    |source_names| and |sink_name_input| are case-insensitive matches.
    |source_names| can include "default_output" or "default_input" to use the default output/input
    and it will automatically switch when the default output/input is changed in system audio settings.
*/
bool gsr_pipewire_audio_add_link_from_sources_to_sink(gsr_pipewire_audio *self, const char **source_names, int num_source_names, const char *sink_name_input);

/* Return true to continue */
typedef bool (*gsr_pipewire_audio_app_query_callback)(const char *app_name, void *userdata);
void gsr_pipewire_audio_for_each_app(gsr_pipewire_audio *self, gsr_pipewire_audio_app_query_callback callback, void *userdata);

#endif /* GSR_PIPEWIRE_AUDIO_H */