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