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 * @title: GstProxyControlBinding
23 * @short_description: attachment for forwarding control sources
24 * @see_also: #GstControlBinding
25 *
26 * A #GstControlBinding that forwards requests to another #GstControlBinding
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "gstproxycontrolbinding.h"
34
35 G_DEFINE_TYPE (GstProxyControlBinding,
36 gst_proxy_control_binding, GST_TYPE_CONTROL_BINDING);
37
38 static void
gst_proxy_control_binding_init(GstProxyControlBinding * self)39 gst_proxy_control_binding_init (GstProxyControlBinding * self)
40 {
41 g_weak_ref_init (&self->ref_object, NULL);
42 }
43
44 static void
gst_proxy_control_binding_finalize(GObject * object)45 gst_proxy_control_binding_finalize (GObject * object)
46 {
47 GstProxyControlBinding *self = (GstProxyControlBinding *) object;
48
49 g_weak_ref_clear (&self->ref_object);
50 g_free (self->property_name);
51
52 G_OBJECT_CLASS (gst_proxy_control_binding_parent_class)->finalize (object);
53 }
54
55 static gboolean
gst_proxy_control_binding_sync_values(GstControlBinding * binding,GstObject * object,GstClockTime timestamp,GstClockTime last_sync)56 gst_proxy_control_binding_sync_values (GstControlBinding * binding,
57 GstObject * object, GstClockTime timestamp, GstClockTime last_sync)
58 {
59 GstProxyControlBinding *self = (GstProxyControlBinding *)
60 binding;
61 gboolean ret = TRUE;
62 GstObject *ref_object;
63
64 ref_object = g_weak_ref_get (&self->ref_object);
65 if (ref_object) {
66 GstControlBinding *ref_binding =
67 gst_object_get_control_binding (ref_object, self->property_name);
68 if (ref_binding) {
69 ret = gst_control_binding_sync_values (ref_binding, ref_object,
70 timestamp, last_sync);
71 gst_object_unref (ref_binding);
72 }
73 gst_object_unref (ref_object);
74 }
75
76 return ret;
77 }
78
79 static GValue *
gst_proxy_control_binding_get_value(GstControlBinding * binding,GstClockTime timestamp)80 gst_proxy_control_binding_get_value (GstControlBinding * binding,
81 GstClockTime timestamp)
82 {
83 GstProxyControlBinding *self = (GstProxyControlBinding *)
84 binding;
85 GValue *ret = NULL;
86 GstObject *ref_object;
87
88 ref_object = g_weak_ref_get (&self->ref_object);
89 if (ref_object) {
90 GstControlBinding *ref_binding =
91 gst_object_get_control_binding (ref_object, self->property_name);
92 if (ref_binding) {
93 ret = gst_control_binding_get_value (ref_binding, timestamp);
94 gst_object_unref (ref_binding);
95 }
96 gst_object_unref (ref_object);
97 }
98
99 return ret;
100 }
101
102 static gboolean
gst_proxy_control_binding_get_value_array(GstControlBinding * binding,GstClockTime timestamp,GstClockTime interval,guint n_values,gpointer values)103 gst_proxy_control_binding_get_value_array (GstControlBinding * binding,
104 GstClockTime timestamp, GstClockTime interval, guint n_values,
105 gpointer values)
106 {
107 GstProxyControlBinding *self = (GstProxyControlBinding *)
108 binding;
109 gboolean ret = FALSE;
110 GstObject *ref_object;
111
112 ref_object = g_weak_ref_get (&self->ref_object);
113 if (ref_object) {
114 GstControlBinding *ref_binding =
115 gst_object_get_control_binding (ref_object, self->property_name);
116 if (ref_binding) {
117 ret = gst_control_binding_get_value_array (ref_binding, timestamp,
118 interval, n_values, values);
119 gst_object_unref (ref_binding);
120 }
121 gst_object_unref (ref_object);
122 }
123
124 return ret;
125 }
126
127 static gboolean
gst_proxy_control_binding_get_g_value_array(GstControlBinding * binding,GstClockTime timestamp,GstClockTime interval,guint n_values,GValue * values)128 gst_proxy_control_binding_get_g_value_array (GstControlBinding *
129 binding, GstClockTime timestamp, GstClockTime interval, guint n_values,
130 GValue * values)
131 {
132 GstProxyControlBinding *self = (GstProxyControlBinding *) binding;
133 gboolean ret = FALSE;
134 GstObject *ref_object;
135
136 ref_object = g_weak_ref_get (&self->ref_object);
137 if (ref_object) {
138 GstControlBinding *ref_binding =
139 gst_object_get_control_binding (ref_object, self->property_name);
140 if (ref_binding) {
141 ret = gst_control_binding_get_g_value_array (ref_binding, timestamp,
142 interval, n_values, values);
143 gst_object_unref (ref_binding);
144 }
145 gst_object_unref (ref_object);
146 }
147
148 return ret;
149 }
150
151 static void
gst_proxy_control_binding_class_init(GstProxyControlBindingClass * klass)152 gst_proxy_control_binding_class_init (GstProxyControlBindingClass * klass)
153 {
154 GstControlBindingClass *cb_class = GST_CONTROL_BINDING_CLASS (klass);
155 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
156
157 cb_class->sync_values = gst_proxy_control_binding_sync_values;
158 cb_class->get_value = gst_proxy_control_binding_get_value;
159 cb_class->get_value_array = gst_proxy_control_binding_get_value_array;
160 cb_class->get_g_value_array = gst_proxy_control_binding_get_g_value_array;
161
162 gobject_class->finalize = gst_proxy_control_binding_finalize;
163 }
164
165 /**
166 * gst_proxy_control_binding_new:
167 * @object: (transfer none): a #GstObject
168 * @property_name: the property name in @object to control
169 * @ref_object: (transfer none): a #GstObject to forward all
170 * #GstControlBinding requests to
171 * @ref_property_name: the property_name in @ref_object to control
172 *
173 * #GstProxyControlBinding forwards all access to data or `sync_values()`
174 * requests from @property_name on @object to the control binding at
175 * @ref_property_name on @ref_object.
176 *
177 * Returns: (transfer floating): a new #GstControlBinding that proxies the control interface between
178 * properties on different #GstObject's
179 *
180 * Since: 1.12
181 */
182 GstControlBinding *
gst_proxy_control_binding_new(GstObject * object,const gchar * property_name,GstObject * ref_object,const gchar * ref_property_name)183 gst_proxy_control_binding_new (GstObject * object, const gchar * property_name,
184 GstObject * ref_object, const gchar * ref_property_name)
185 {
186 GstProxyControlBinding *cb;
187
188 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
189 g_return_val_if_fail (property_name != NULL, NULL);
190 g_return_val_if_fail (GST_IS_OBJECT (ref_object), NULL);
191 g_return_val_if_fail (ref_property_name != NULL, NULL);
192
193 cb = g_object_new (GST_TYPE_PROXY_CONTROL_BINDING, "object", object,
194 "name", property_name, NULL);
195
196 g_weak_ref_set (&cb->ref_object, ref_object);
197 cb->property_name = g_strdup (ref_property_name);
198
199 return (GstControlBinding *) cb;
200 }
201