• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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