1 /*
2  * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <string.h>
19 #include <glib.h>
20 #include <glib-object.h>
21 
22 #include "matemixer-enums.h"
23 #include "matemixer-enum-types.h"
24 #include "matemixer-switch.h"
25 #include "matemixer-switch-private.h"
26 #include "matemixer-switch-option.h"
27 
28 /**
29  * SECTION:matemixer-switch
30  * @include: libmatemixer/matemixer.h
31  */
32 
33 struct _MateMixerSwitchPrivate
34 {
35     gchar                 *name;
36     gchar                 *label;
37     MateMixerSwitchOption *active;
38 };
39 
40 enum {
41     PROP_0,
42     PROP_NAME,
43     PROP_LABEL,
44     PROP_ACTIVE_OPTION,
45     N_PROPERTIES
46 };
47 
48 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
49 
50 static void mate_mixer_switch_get_property (GObject              *object,
51                                             guint                 param_id,
52                                             GValue               *value,
53                                             GParamSpec           *pspec);
54 static void mate_mixer_switch_set_property (GObject              *object,
55                                             guint                 param_id,
56                                             const GValue         *value,
57                                             GParamSpec           *pspec);
58 
59 static void mate_mixer_switch_dispose      (GObject              *object);
60 static void mate_mixer_switch_finalize     (GObject              *object);
61 
62 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MateMixerSwitch, mate_mixer_switch, G_TYPE_OBJECT)
63 
64 static MateMixerSwitchOption *mate_mixer_switch_real_get_option (MateMixerSwitch *swtch,
65                                                                  const gchar     *name);
66 
67 static void
mate_mixer_switch_class_init(MateMixerSwitchClass * klass)68 mate_mixer_switch_class_init (MateMixerSwitchClass *klass)
69 {
70     GObjectClass *object_class;
71 
72     klass->get_option = mate_mixer_switch_real_get_option;
73 
74     object_class = G_OBJECT_CLASS (klass);
75     object_class->dispose      = mate_mixer_switch_dispose;
76     object_class->finalize     = mate_mixer_switch_finalize;
77     object_class->get_property = mate_mixer_switch_get_property;
78     object_class->set_property = mate_mixer_switch_set_property;
79 
80     properties[PROP_NAME] =
81         g_param_spec_string ("name",
82                              "Name",
83                              "Name of the switch",
84                              NULL,
85                              G_PARAM_READWRITE |
86                              G_PARAM_CONSTRUCT_ONLY |
87                              G_PARAM_STATIC_STRINGS);
88 
89     properties[PROP_LABEL] =
90         g_param_spec_string ("label",
91                              "Label",
92                              "Label of the switch",
93                              NULL,
94                              G_PARAM_READWRITE |
95                              G_PARAM_CONSTRUCT_ONLY |
96                              G_PARAM_STATIC_STRINGS);
97 
98     properties[PROP_ACTIVE_OPTION] =
99         g_param_spec_object ("active-option",
100                              "Active option",
101                              "Active option of the switch",
102                              MATE_MIXER_TYPE_SWITCH_OPTION,
103                              G_PARAM_READWRITE |
104                              G_PARAM_CONSTRUCT_ONLY |
105                              G_PARAM_STATIC_STRINGS);
106 
107     g_object_class_install_properties (object_class, N_PROPERTIES, properties);
108 }
109 
110 static void
mate_mixer_switch_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)111 mate_mixer_switch_get_property (GObject    *object,
112                                 guint       param_id,
113                                 GValue     *value,
114                                 GParamSpec *pspec)
115 {
116     MateMixerSwitch *swtch;
117 
118     swtch = MATE_MIXER_SWITCH (object);
119 
120     switch (param_id) {
121     case PROP_NAME:
122         g_value_set_string (value, swtch->priv->name);
123         break;
124     case PROP_LABEL:
125         g_value_set_string (value, swtch->priv->label);
126         break;
127     case PROP_ACTIVE_OPTION:
128         g_value_set_object (value, swtch->priv->active);
129         break;
130 
131     default:
132         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
133         break;
134     }
135 }
136 
137 static void
mate_mixer_switch_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)138 mate_mixer_switch_set_property (GObject      *object,
139                                 guint         param_id,
140                                 const GValue *value,
141                                 GParamSpec   *pspec)
142 {
143     MateMixerSwitch *swtch;
144 
145     swtch = MATE_MIXER_SWITCH (object);
146 
147     switch (param_id) {
148     case PROP_NAME:
149         /* Construct-only string */
150         swtch->priv->name = g_value_dup_string (value);
151         break;
152     case PROP_LABEL:
153         /* Construct-only string */
154         swtch->priv->label = g_value_dup_string (value);
155         break;
156     case PROP_ACTIVE_OPTION:
157         /* Construct-only object */
158         swtch->priv->active = g_value_dup_object (value);
159         break;
160 
161     default:
162         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
163         break;
164     }
165 }
166 
167 static void
mate_mixer_switch_init(MateMixerSwitch * swtch)168 mate_mixer_switch_init (MateMixerSwitch *swtch)
169 {
170     swtch->priv = mate_mixer_switch_get_instance_private (swtch);
171 }
172 
173 static void
mate_mixer_switch_dispose(GObject * object)174 mate_mixer_switch_dispose (GObject *object)
175 {
176     MateMixerSwitch *swtch;
177 
178     swtch = MATE_MIXER_SWITCH (object);
179 
180     g_clear_object (&swtch->priv->active);
181 
182     G_OBJECT_CLASS (mate_mixer_switch_parent_class)->dispose (object);
183 }
184 
185 static void
mate_mixer_switch_finalize(GObject * object)186 mate_mixer_switch_finalize (GObject *object)
187 {
188     MateMixerSwitch *swtch;
189 
190     swtch = MATE_MIXER_SWITCH (object);
191 
192     g_free (swtch->priv->name);
193     g_free (swtch->priv->label);
194 
195     G_OBJECT_CLASS (mate_mixer_switch_parent_class)->finalize (object);
196 }
197 
198 /**
199  * mate_mixer_switch_get_name:
200  * @swtch: a #MateMixerSwitch
201  *
202  * Gets the name of the switch.
203  *
204  * The name serves as a unique identifier and in most cases it is not in a
205  * user-readable form.
206  *
207  * Returns: the name of the switch.
208  */
209 const gchar *
mate_mixer_switch_get_name(MateMixerSwitch * swtch)210 mate_mixer_switch_get_name (MateMixerSwitch *swtch)
211 {
212     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
213 
214     return swtch->priv->name;
215 }
216 
217 /**
218  * mate_mixer_switch_get_label:
219  * @swtch: a #MateMixerSwitch
220  *
221  * Gets the label of the switch.
222  *
223  * This is a potentially translated string that should be presented to users
224  * in the user interface.
225  *
226  * Returns: the label of the switch option.
227  */
228 const gchar *
mate_mixer_switch_get_label(MateMixerSwitch * swtch)229 mate_mixer_switch_get_label (MateMixerSwitch *swtch)
230 {
231     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
232 
233     return swtch->priv->label;
234 }
235 
236 /**
237  * mate_mixer_switch_get_option:
238  * @swtch: a #MateMixerSwitch
239  * @name: the name of an option
240  *
241  * Gets the #MateMixerSwitchOption with the given name.
242  *
243  * Returns: a #MateMixerSwitchOption or %NULL if there is no such switch option.
244  */
245 MateMixerSwitchOption *
mate_mixer_switch_get_option(MateMixerSwitch * swtch,const gchar * name)246 mate_mixer_switch_get_option (MateMixerSwitch *swtch, const gchar *name)
247 {
248     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
249     g_return_val_if_fail (name != NULL, NULL);
250 
251     return MATE_MIXER_SWITCH_GET_CLASS (swtch)->get_option (swtch, name);
252 }
253 
254 /**
255  * mate_mixer_switch_get_active_option:
256  * @swtch: a #MateMixerSwitch
257  *
258  * Gets the #MateMixerSwitchOption which is currently active.
259  *
260  * Returns: a #MateMixerSwitchOption.
261  */
262 MateMixerSwitchOption *
mate_mixer_switch_get_active_option(MateMixerSwitch * swtch)263 mate_mixer_switch_get_active_option (MateMixerSwitch *swtch)
264 {
265     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
266 
267     return swtch->priv->active;
268 }
269 
270 /**
271  * mate_mixer_switch_set_active_option:
272  * @swtch: a #MateMixerSwitch
273  * @option: the #MateMixerSwitchOption to set as the active option
274  *
275  * Changes the currently active switch option.
276  *
277  * Returns: %TRUE on success or %FALSE on failure.
278  */
279 gboolean
mate_mixer_switch_set_active_option(MateMixerSwitch * swtch,MateMixerSwitchOption * option)280 mate_mixer_switch_set_active_option (MateMixerSwitch       *swtch,
281                                      MateMixerSwitchOption *option)
282 {
283     MateMixerSwitchClass *klass;
284 
285     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), FALSE);
286     g_return_val_if_fail (MATE_MIXER_IS_SWITCH_OPTION (option), FALSE);
287 
288     klass = MATE_MIXER_SWITCH_GET_CLASS (swtch);
289     if (klass->set_active_option == NULL)
290         return FALSE;
291 
292     if (swtch->priv->active != option) {
293         if (klass->set_active_option (swtch, option) == FALSE)
294             return FALSE;
295 
296         _mate_mixer_switch_set_active_option (swtch, option);
297     }
298     return TRUE;
299 }
300 
301 /**
302  * mate_mixer_switch_list_options:
303  * @swtch: a #MateMixerSwitch
304  *
305  * Gets the list of switch options that belong to the switch.
306  *
307  * The returned #GList is owned by the #MateMixerSwitch and may be invalidated
308  * at any time.
309  *
310  * Returns: a #GList of the switch options.
311  */
312 const GList *
mate_mixer_switch_list_options(MateMixerSwitch * swtch)313 mate_mixer_switch_list_options (MateMixerSwitch *swtch)
314 {
315     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
316 
317     return MATE_MIXER_SWITCH_GET_CLASS (swtch)->list_options (swtch);
318 }
319 
320 /* Protected functions */
321 void
_mate_mixer_switch_set_active_option(MateMixerSwitch * swtch,MateMixerSwitchOption * option)322 _mate_mixer_switch_set_active_option (MateMixerSwitch       *swtch,
323                                       MateMixerSwitchOption *option)
324 {
325     g_return_if_fail (MATE_MIXER_IS_SWITCH (swtch));
326     g_return_if_fail (MATE_MIXER_IS_SWITCH_OPTION (option));
327 
328     if (swtch->priv->active == option)
329         return;
330 
331     if (swtch->priv->active != NULL)
332         g_object_unref (swtch->priv->active);
333 
334     swtch->priv->active = g_object_ref (option);
335 
336     g_object_notify_by_pspec (G_OBJECT (swtch), properties[PROP_ACTIVE_OPTION]);
337 }
338 
339 static MateMixerSwitchOption *
mate_mixer_switch_real_get_option(MateMixerSwitch * swtch,const gchar * name)340 mate_mixer_switch_real_get_option (MateMixerSwitch *swtch, const gchar *name)
341 {
342     const GList *list;
343 
344     g_return_val_if_fail (MATE_MIXER_IS_SWITCH (swtch), NULL);
345     g_return_val_if_fail (name != NULL, NULL);
346 
347     list = mate_mixer_switch_list_options (swtch);
348     while (list != NULL) {
349         MateMixerSwitchOption *option = MATE_MIXER_SWITCH_OPTION (list->data);
350 
351         if (strcmp (name, mate_mixer_switch_option_get_name (option)) == 0)
352             return option;
353 
354         list = list->next;
355     }
356     return NULL;
357 }
358