ce5cad5d832d99dc9e9e3f6b7bda374f54f3de17
[platform/upstream/gstreamer.git] / libs / gst / controller / gstproxycontrolbinding.c
1 /*
2  * GStreamer
3  * Copyright (C) 2016 Matthew Waters <matthew@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 /**
21  * SECTION:gstproxycontrolbinding
22  * @short_description: attachment for forwarding control sources
23  * @see_also: #GstControlBinding
24  *
25  * A #GstControlBinding that forwards requests to another #GstControlBinding
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "gstproxycontrolbinding.h"
33
34 G_DEFINE_TYPE (GstProxyControlBinding,
35     gst_proxy_control_binding, GST_TYPE_CONTROL_BINDING);
36
37 static void
38 gst_proxy_control_binding_init (GstProxyControlBinding * self)
39 {
40   g_weak_ref_init (&self->ref_object, NULL);
41 }
42
43 static void
44 gst_proxy_control_binding_finalize (GObject * object)
45 {
46   GstProxyControlBinding *self = (GstProxyControlBinding *) object;
47
48   g_weak_ref_clear (&self->ref_object);
49   g_free (self->property_name);
50
51   G_OBJECT_CLASS (gst_proxy_control_binding_parent_class)->finalize (object);
52 }
53
54 static gboolean
55 gst_proxy_control_binding_sync_values (GstControlBinding * binding,
56     GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
57 {
58   GstProxyControlBinding *self = (GstProxyControlBinding *)
59       binding;
60   gboolean ret = TRUE;
61   GstObject *ref_object;
62
63   ref_object = g_weak_ref_get (&self->ref_object);
64   if (ref_object) {
65     GstControlBinding *ref_binding =
66         gst_object_get_control_binding (ref_object, self->property_name);
67     if (ref_binding) {
68       ret = gst_control_binding_sync_values (ref_binding, ref_object,
69           timestamp, last_sync);
70       gst_object_unref (ref_binding);
71     }
72     gst_object_unref (ref_object);
73   }
74
75   return ret;
76 }
77
78 static GValue *
79 gst_proxy_control_binding_get_value (GstControlBinding * binding,
80     GstClockTime timestamp)
81 {
82   GstProxyControlBinding *self = (GstProxyControlBinding *)
83       binding;
84   GValue *ret = NULL;
85   GstObject *ref_object;
86
87   ref_object = g_weak_ref_get (&self->ref_object);
88   if (ref_object) {
89     GstControlBinding *ref_binding =
90         gst_object_get_control_binding (ref_object, self->property_name);
91     if (ref_binding) {
92       ret = gst_control_binding_get_value (ref_binding, timestamp);
93       gst_object_unref (ref_binding);
94     }
95     gst_object_unref (ref_object);
96   }
97
98   return ret;
99 }
100
101 static gboolean
102 gst_proxy_control_binding_get_value_array (GstControlBinding * binding,
103     GstClockTime timestamp, GstClockTime interval, guint n_values,
104     gpointer values)
105 {
106   GstProxyControlBinding *self = (GstProxyControlBinding *)
107       binding;
108   gboolean ret = FALSE;
109   GstObject *ref_object;
110
111   ref_object = g_weak_ref_get (&self->ref_object);
112   if (ref_object) {
113     GstControlBinding *ref_binding =
114         gst_object_get_control_binding (ref_object, self->property_name);
115     if (ref_binding) {
116       ret = gst_control_binding_get_value_array (ref_binding, timestamp,
117           interval, n_values, values);
118       gst_object_unref (ref_binding);
119     }
120     gst_object_unref (ref_object);
121   }
122
123   return ret;
124 }
125
126 static gboolean
127 gst_proxy_control_binding_get_g_value_array (GstControlBinding *
128     binding, GstClockTime timestamp, GstClockTime interval, guint n_values,
129     GValue * values)
130 {
131   GstProxyControlBinding *self = (GstProxyControlBinding *) binding;
132   gboolean ret = FALSE;
133   GstObject *ref_object;
134
135   ref_object = g_weak_ref_get (&self->ref_object);
136   if (ref_object) {
137     GstControlBinding *ref_binding =
138         gst_object_get_control_binding (ref_object, self->property_name);
139     if (ref_binding) {
140       ret = gst_control_binding_get_g_value_array (ref_binding, timestamp,
141           interval, n_values, values);
142       gst_object_unref (ref_binding);
143     }
144     gst_object_unref (ref_object);
145   }
146
147   return ret;
148 }
149
150 static void
151 gst_proxy_control_binding_class_init (GstProxyControlBindingClass * klass)
152 {
153   GstControlBindingClass *cb_class = GST_CONTROL_BINDING_CLASS (klass);
154   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
155
156   cb_class->sync_values = gst_proxy_control_binding_sync_values;
157   cb_class->get_value = gst_proxy_control_binding_get_value;
158   cb_class->get_value_array = gst_proxy_control_binding_get_value_array;
159   cb_class->get_g_value_array = gst_proxy_control_binding_get_g_value_array;
160
161   gobject_class->finalize = gst_proxy_control_binding_finalize;
162 }
163
164 /**
165  * gst_proxy_control_binding_new:
166  * @object: (transfer none): a #GstObject
167  * @property_name: the property name in @object to control
168  * @ref_object: (transfer none): a #GstObject to forward all
169  *              #GstControlBinding requests to
170  * @ref_property_name: the property_name in @ref_object to control
171  *
172  * #GstProxyControlBinding forwards all access to data or sync_values()
173  * requests from @property_name on @object to the control binding at
174  * @ref_property_name on @ref_object.
175  *
176  * Returns: a new #GstControlBinding that proxies the control interface between
177  * properties on different #GstObject's
178  *
179  * Since: 1.12
180  */
181 GstControlBinding *
182 gst_proxy_control_binding_new (GstObject * object, const gchar * property_name,
183     GstObject * ref_object, const gchar * ref_property_name)
184 {
185   GstProxyControlBinding *cb;
186
187   g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
188   g_return_val_if_fail (property_name != NULL, NULL);
189   g_return_val_if_fail (GST_IS_OBJECT (ref_object), NULL);
190   g_return_val_if_fail (ref_property_name != NULL, NULL);
191
192   cb = g_object_new (GST_TYPE_PROXY_CONTROL_BINDING, "object", object,
193       "name", property_name, NULL);
194
195   g_weak_ref_set (&cb->ref_object, ref_object);
196   cb->property_name = g_strdup (ref_property_name);
197
198   return (GstControlBinding *) cb;
199 }