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-pa-stream"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <math.h>
9 : :
10 : : #include <gvc-mixer-stream.h>
11 : : #include <valent.h>
12 : :
13 : : #include "valent-pa-stream.h"
14 : :
15 : : #define _PA_VOLUME_NORM ((pa_volume_t) 0x10000U)
16 : :
17 : : struct _ValentPaStream
18 : : {
19 : : ValentMixerStream parent_instance;
20 : :
21 : : GvcMixerStream *stream;
22 : : char *description;
23 : : };
24 : :
25 : 0 : G_DEFINE_FINAL_TYPE (ValentPaStream, valent_pa_stream, VALENT_TYPE_MIXER_STREAM)
26 : :
27 : : enum {
28 : : PROP_0,
29 : : PROP_BASE_STREAM,
30 : : N_PROPERTIES
31 : : };
32 : :
33 : : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
34 : :
35 : :
36 : : static void
37 : 0 : on_port_changed (GvcMixerStream *stream,
38 : : GParamSpec *pspec,
39 : : ValentPaStream *self)
40 : : {
41 : 0 : const GvcMixerStreamPort *port;
42 : :
43 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
44 : :
45 : 0 : g_clear_pointer (&self->description, g_free);
46 : :
47 : 0 : if ((port = gvc_mixer_stream_get_port (self->stream)) != NULL)
48 : : {
49 : 0 : const char *description;
50 : :
51 : 0 : description = gvc_mixer_stream_get_description (self->stream);
52 : 0 : self->description = g_strdup_printf ("%s (%s)",
53 : 0 : port->human_port,
54 : : description);
55 : : }
56 : :
57 : 0 : g_object_notify (G_OBJECT (self), "description");
58 : 0 : }
59 : :
60 : : /*
61 : : * ValentMixerStream
62 : : */
63 : : static const char *
64 : 0 : valent_pa_stream_get_description (ValentMixerStream *stream)
65 : : {
66 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
67 : :
68 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
69 : :
70 : 0 : if (self->description == NULL)
71 : 0 : return gvc_mixer_stream_get_description (self->stream);
72 : :
73 : : return self->description;
74 : : }
75 : :
76 : : static unsigned int
77 : 0 : valent_pa_stream_get_level (ValentMixerStream *stream)
78 : : {
79 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
80 : 0 : pa_volume_t volume;
81 : 0 : double percent;
82 : :
83 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
84 : 0 : g_assert (GVC_IS_MIXER_STREAM (self->stream));
85 : :
86 : 0 : volume = gvc_mixer_stream_get_volume (self->stream);
87 : 0 : percent = (double)volume / (double)_PA_VOLUME_NORM;
88 : :
89 : 0 : return (unsigned int)round (percent * 100.0);
90 : : }
91 : :
92 : : static void
93 : 0 : valent_pa_stream_set_level (ValentMixerStream *stream,
94 : : unsigned int level)
95 : : {
96 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
97 : 0 : double percent;
98 : 0 : pa_volume_t volume;
99 : :
100 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
101 : 0 : g_assert (GVC_IS_MIXER_STREAM (self->stream));
102 : :
103 : 0 : percent = (double)level / 100.0;
104 : 0 : volume = (pa_volume_t)round (percent * _PA_VOLUME_NORM);
105 : :
106 : 0 : gvc_mixer_stream_set_volume (self->stream, (pa_volume_t)volume);
107 : 0 : gvc_mixer_stream_push_volume (self->stream);
108 : 0 : g_object_notify (G_OBJECT (stream), "level");
109 : 0 : }
110 : :
111 : : static gboolean
112 : 0 : valent_pa_stream_get_muted (ValentMixerStream *stream)
113 : : {
114 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
115 : :
116 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
117 : 0 : g_assert (GVC_IS_MIXER_STREAM (self->stream));
118 : :
119 : 0 : return gvc_mixer_stream_get_is_muted (self->stream);
120 : : }
121 : :
122 : : static void
123 : 0 : valent_pa_stream_set_muted (ValentMixerStream *stream,
124 : : gboolean state)
125 : : {
126 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
127 : :
128 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
129 : 0 : g_assert (GVC_IS_MIXER_STREAM (self->stream));
130 : :
131 : 0 : gvc_mixer_stream_change_is_muted (self->stream, state);
132 : 0 : g_object_notify (G_OBJECT (stream), "muted");
133 : 0 : }
134 : :
135 : : static const char *
136 : 0 : valent_pa_stream_get_name (ValentMixerStream *stream)
137 : : {
138 : 0 : ValentPaStream *self = VALENT_PA_STREAM (stream);
139 : :
140 : 0 : g_assert (VALENT_IS_PA_STREAM (self));
141 : 0 : g_assert (GVC_IS_MIXER_STREAM (self->stream));
142 : :
143 : 0 : return gvc_mixer_stream_get_name (self->stream);
144 : : }
145 : :
146 : : /*
147 : : * GObject
148 : : */
149 : : static void
150 : 0 : valent_pa_stream_get_property (GObject *object,
151 : : guint prop_id,
152 : : GValue *value,
153 : : GParamSpec *pspec)
154 : : {
155 : 0 : ValentPaStream *self = VALENT_PA_STREAM (object);
156 : :
157 : 0 : switch (prop_id)
158 : : {
159 : 0 : case PROP_BASE_STREAM:
160 : 0 : g_value_set_object (value, self->stream);
161 : 0 : break;
162 : :
163 : 0 : default:
164 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
165 : : }
166 : 0 : }
167 : :
168 : : static void
169 : 0 : valent_pa_stream_set_property (GObject *object,
170 : : guint prop_id,
171 : : const GValue *value,
172 : : GParamSpec *pspec)
173 : : {
174 : 0 : ValentPaStream *self = VALENT_PA_STREAM (object);
175 : :
176 : 0 : switch (prop_id)
177 : : {
178 : 0 : case PROP_BASE_STREAM:
179 : 0 : self->stream = g_value_dup_object (value);
180 : 0 : break;
181 : :
182 : 0 : default:
183 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
184 : : }
185 : 0 : }
186 : :
187 : : static void
188 : 0 : valent_pa_stream_constructed (GObject *object)
189 : : {
190 : 0 : ValentPaStream *self = VALENT_PA_STREAM (object);
191 : :
192 : 0 : g_assert (self->stream != NULL);
193 : :
194 : 0 : g_signal_connect_object (self->stream,
195 : : "notify::port",
196 : : G_CALLBACK (on_port_changed),
197 : : self, 0);
198 : 0 : on_port_changed (self->stream, NULL, self);
199 : :
200 : 0 : G_OBJECT_CLASS (valent_pa_stream_parent_class)->constructed (object);
201 : 0 : }
202 : :
203 : : static void
204 : 0 : valent_pa_stream_finalize (GObject *object)
205 : : {
206 : 0 : ValentPaStream *self = VALENT_PA_STREAM (object);
207 : :
208 : 0 : g_signal_handlers_disconnect_by_data (self->stream, self);
209 : 0 : g_clear_object (&self->stream);
210 : :
211 : 0 : G_OBJECT_CLASS (valent_pa_stream_parent_class)->finalize (object);
212 : 0 : }
213 : :
214 : : static void
215 : 0 : valent_pa_stream_class_init (ValentPaStreamClass *klass)
216 : : {
217 : 0 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
218 : 0 : ValentMixerStreamClass *stream_class = VALENT_MIXER_STREAM_CLASS (klass);
219 : :
220 : 0 : object_class->constructed = valent_pa_stream_constructed;
221 : 0 : object_class->finalize = valent_pa_stream_finalize;
222 : 0 : object_class->get_property = valent_pa_stream_get_property;
223 : 0 : object_class->set_property = valent_pa_stream_set_property;
224 : :
225 : 0 : stream_class->get_name = valent_pa_stream_get_name;
226 : 0 : stream_class->get_description = valent_pa_stream_get_description;
227 : 0 : stream_class->get_level = valent_pa_stream_get_level;
228 : 0 : stream_class->set_level = valent_pa_stream_set_level;
229 : 0 : stream_class->get_muted = valent_pa_stream_get_muted;
230 : 0 : stream_class->set_muted = valent_pa_stream_set_muted;
231 : :
232 : : /**
233 : : * ValentPaStream:base-stream:
234 : : *
235 : : * The `GvcMixerStream` this stream wraps.
236 : : */
237 : 0 : properties [PROP_BASE_STREAM] =
238 : 0 : g_param_spec_object ("base-stream", NULL, NULL,
239 : : GVC_TYPE_MIXER_STREAM,
240 : : (G_PARAM_READWRITE |
241 : : G_PARAM_CONSTRUCT_ONLY |
242 : : G_PARAM_EXPLICIT_NOTIFY |
243 : : G_PARAM_STATIC_STRINGS));
244 : :
245 : 0 : g_object_class_install_properties (object_class, N_PROPERTIES, properties);
246 : 0 : }
247 : :
248 : : static void
249 : 0 : valent_pa_stream_init (ValentPaStream *self)
250 : : {
251 : 0 : }
252 : :
|