aboutsummaryrefslogtreecommitdiff
path: root/include/pipewire_audio.h
blob: 1cf666687e2322bcbb5e82459cfa9575a0ce6cbd (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>

#define GSR_PIPEWIRE_AUDIO_MAX_STREAM_NODES 128
#define GSR_PIPEWIRE_AUDIO_MAX_PORTS 256
#define GSR_PIPEWIRE_AUDIO_MAX_LINKS 256
#define GSR_PIPEWIRE_AUDIO_MAX_REQUESTED_LINKS 32
#define GSR_PIPEWIRE_AUDIO_MAX_VIRTUAL_SINKS 32

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;
    char default_output_device_name[128];
    char default_input_device_name[128];

    gsr_pipewire_audio_node stream_nodes[GSR_PIPEWIRE_AUDIO_MAX_STREAM_NODES];
    int num_stream_nodes;

    gsr_pipewire_audio_port ports[GSR_PIPEWIRE_AUDIO_MAX_PORTS];
    int num_ports;

    gsr_pipewire_audio_link links[GSR_PIPEWIRE_AUDIO_MAX_LINKS];
    int num_links;

    gsr_pipewire_audio_requested_link requested_links[GSR_PIPEWIRE_AUDIO_MAX_REQUESTED_LINKS];
    int num_requested_links;

    struct pw_proxy *virtual_sink_proxies[GSR_PIPEWIRE_AUDIO_MAX_VIRTUAL_SINKS];
    int num_virtual_sink_proxies;
} 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 */