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