Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-pipewire-stream"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <math.h>
9 : :
10 : : #include <pipewire/pipewire.h>
11 : : #include <valent.h>
12 : :
13 : : #include "valent-pipewire-mixer.h"
14 : : #include "valent-pipewire-stream.h"
15 : :
16 : :
17 : : struct _ValentPipewireStream
18 : : {
19 : : ValentMixerStream parent_instance;
20 : :
21 : : ValentPipewireMixer *adapter;
22 : : uint32_t device_id;
23 : : uint32_t node_id;
24 : :
25 : : char *description;
26 : : unsigned int level;
27 : : gboolean muted;
28 : : };
29 : :
30 : 0 : G_DEFINE_FINAL_TYPE (ValentPipewireStream, valent_pipewire_stream, VALENT_TYPE_MIXER_STREAM)
31 : :
32 : : enum {
33 : : PROP_0,
34 : : PROP_ADAPTER,
35 : : PROP_DEVICE_ID,
36 : : PROP_NODE_ID,
37 : : N_PROPERTIES
38 : : };
39 : :
40 : : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
41 : :
42 : :
43 : : /*
44 : : * ValentMixerStream
45 : : */
46 : : static const char *
47 : 0 : valent_pipewire_stream_get_description (ValentMixerStream *stream)
48 : : {
49 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (stream);
50 : :
51 : 0 : g_assert (VALENT_IS_PIPEWIRE_STREAM (self));
52 : :
53 : 0 : return self->description;
54 : : }
55 : :
56 : : static unsigned int
57 : 0 : valent_pipewire_stream_get_level (ValentMixerStream *stream)
58 : : {
59 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (stream);
60 : :
61 : 0 : g_assert (VALENT_IS_PIPEWIRE_STREAM (self));
62 : :
63 : 0 : return self->level;
64 : : }
65 : :
66 : : static void
67 : 0 : valent_pipewire_stream_set_level (ValentMixerStream *stream,
68 : : unsigned int level)
69 : : {
70 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (stream);
71 : :
72 : 0 : g_assert (VALENT_IS_PIPEWIRE_STREAM (self));
73 : :
74 : 0 : if (self->level == level || self->adapter == NULL)
75 : : return;
76 : :
77 : 0 : valent_pipewire_mixer_set_stream_state (self->adapter,
78 : : self->device_id,
79 : : self->node_id,
80 : : level,
81 : : self->muted);
82 : : }
83 : :
84 : : static gboolean
85 : 0 : valent_pipewire_stream_get_muted (ValentMixerStream *stream)
86 : : {
87 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (stream);
88 : :
89 : 0 : g_assert (VALENT_IS_PIPEWIRE_STREAM (self));
90 : :
91 : 0 : return self->muted;
92 : : }
93 : :
94 : : static void
95 : 0 : valent_pipewire_stream_set_muted (ValentMixerStream *stream,
96 : : gboolean state)
97 : : {
98 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (stream);
99 : :
100 : 0 : g_assert (VALENT_IS_PIPEWIRE_STREAM (self));
101 : :
102 : 0 : if (self->muted == state || self->adapter == NULL)
103 : : return;
104 : :
105 : 0 : valent_pipewire_mixer_set_stream_state (self->adapter,
106 : : self->device_id,
107 : : self->node_id,
108 : : self->level,
109 : : state);
110 : : }
111 : :
112 : : /*
113 : : * GObject
114 : : */
115 : : static void
116 : 0 : valent_pipewire_stream_get_property (GObject *object,
117 : : guint prop_id,
118 : : GValue *value,
119 : : GParamSpec *pspec)
120 : : {
121 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (object);
122 : :
123 : 0 : switch (prop_id)
124 : : {
125 : 0 : case PROP_ADAPTER:
126 : 0 : g_value_set_object (value, self->adapter);
127 : 0 : break;
128 : :
129 : 0 : case PROP_DEVICE_ID:
130 : 0 : g_value_set_uint (value, self->device_id);
131 : 0 : break;
132 : :
133 : 0 : case PROP_NODE_ID:
134 : 0 : g_value_set_uint (value, self->node_id);
135 : 0 : break;
136 : :
137 : 0 : default:
138 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
139 : : }
140 : 0 : }
141 : :
142 : : static void
143 : 0 : valent_pipewire_stream_set_property (GObject *object,
144 : : guint prop_id,
145 : : const GValue *value,
146 : : GParamSpec *pspec)
147 : : {
148 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (object);
149 : :
150 : 0 : switch (prop_id)
151 : : {
152 : 0 : case PROP_ADAPTER:
153 : 0 : self->adapter = g_value_get_object (value);
154 : 0 : g_object_add_weak_pointer (G_OBJECT (self->adapter),
155 : 0 : (gpointer *)&self->adapter);
156 : 0 : break;
157 : :
158 : 0 : case PROP_DEVICE_ID:
159 : 0 : self->device_id = g_value_get_uint (value);
160 : 0 : break;
161 : :
162 : 0 : case PROP_NODE_ID:
163 : 0 : self->node_id = g_value_get_uint (value);
164 : 0 : break;
165 : :
166 : 0 : default:
167 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168 : : }
169 : 0 : }
170 : :
171 : : static void
172 : 0 : valent_pipewire_stream_finalize (GObject *object)
173 : : {
174 : 0 : ValentPipewireStream *self = VALENT_PIPEWIRE_STREAM (object);
175 : :
176 : 0 : g_clear_weak_pointer (&self->adapter);
177 : 0 : g_clear_pointer (&self->description, g_free);
178 : :
179 : 0 : G_OBJECT_CLASS (valent_pipewire_stream_parent_class)->finalize (object);
180 : 0 : }
181 : :
182 : : static void
183 : 0 : valent_pipewire_stream_class_init (ValentPipewireStreamClass *klass)
184 : : {
185 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
186 : 0 : ValentMixerStreamClass *stream_class = VALENT_MIXER_STREAM_CLASS (klass);
187 : :
188 : 0 : object_class->finalize = valent_pipewire_stream_finalize;
189 : 0 : object_class->get_property = valent_pipewire_stream_get_property;
190 : 0 : object_class->set_property = valent_pipewire_stream_set_property;
191 : :
192 : 0 : stream_class->get_description = valent_pipewire_stream_get_description;
193 : 0 : stream_class->get_level = valent_pipewire_stream_get_level;
194 : 0 : stream_class->set_level = valent_pipewire_stream_set_level;
195 : 0 : stream_class->get_muted = valent_pipewire_stream_get_muted;
196 : 0 : stream_class->set_muted = valent_pipewire_stream_set_muted;
197 : :
198 : : /**
199 : : * ValentPaStream:adapter:
200 : : *
201 : : * The #GvcMixerStream this stream wraps.
202 : : */
203 : 0 : properties [PROP_ADAPTER] =
204 : 0 : g_param_spec_object ("adapter", NULL, NULL,
205 : : VALENT_TYPE_PIPEWIRE_MIXER,
206 : : (G_PARAM_READWRITE |
207 : : G_PARAM_CONSTRUCT_ONLY |
208 : : G_PARAM_EXPLICIT_NOTIFY |
209 : : G_PARAM_STATIC_STRINGS));
210 : :
211 : : /**
212 : : * ValentPaStream:device-id:
213 : : *
214 : : * The PipeWire device ID.
215 : : */
216 : 0 : properties [PROP_DEVICE_ID] =
217 : 0 : g_param_spec_uint ("device-id", NULL, NULL,
218 : : 0, G_MAXUINT32,
219 : : 0,
220 : : (G_PARAM_READWRITE |
221 : : G_PARAM_CONSTRUCT_ONLY |
222 : : G_PARAM_EXPLICIT_NOTIFY |
223 : : G_PARAM_STATIC_STRINGS));
224 : :
225 : : /**
226 : : * ValentPaStream:node-id:
227 : : *
228 : : * The PipeWire node ID.
229 : : */
230 : 0 : properties [PROP_NODE_ID] =
231 : 0 : g_param_spec_uint ("node-id", NULL, NULL,
232 : : 0, G_MAXUINT32,
233 : : 0,
234 : : (G_PARAM_READWRITE |
235 : : G_PARAM_CONSTRUCT_ONLY |
236 : : G_PARAM_EXPLICIT_NOTIFY |
237 : : G_PARAM_STATIC_STRINGS));
238 : :
239 : 0 : g_object_class_install_properties (object_class, N_PROPERTIES, properties);
240 : 0 : }
241 : :
242 : : static void
243 : 0 : valent_pipewire_stream_init (ValentPipewireStream *self)
244 : : {
245 : 0 : }
246 : :
247 : : /*< private >
248 : : * valent_pipewire_stream_update:
249 : : * @stream: `ValentPipewireStream`
250 : : * @description: the new description
251 : : * @level: the new volume level
252 : : * @state: the new mute state
253 : : *
254 : : * Update the stream state.
255 : : */
256 : : void
257 : 0 : valent_pipewire_stream_update (ValentPipewireStream *stream,
258 : : const char *description,
259 : : uint32_t level,
260 : : gboolean state)
261 : : {
262 : 0 : g_return_if_fail (VALENT_IS_MIXER_STREAM (stream));
263 : :
264 : 0 : if (g_set_str (&stream->description, description))
265 : 0 : g_object_notify (G_OBJECT (stream), "description");
266 : :
267 : 0 : if (stream->level != level)
268 : : {
269 : 0 : stream->level = level;
270 : 0 : g_object_notify (G_OBJECT (stream), "level");
271 : : }
272 : :
273 : 0 : if (stream->muted != state)
274 : : {
275 : 0 : stream->muted = state;
276 : 0 : g_object_notify (G_OBJECT (stream), "muted");
277 : : }
278 : : }
279 : :
|