Move dataurisrc element from -bad
[platform/upstream/gstreamer.git] / gst / gstdevice.c
1 /* GStreamer
2  * Copyright (C) 2012 Olivier Crete <olivier.crete@collabora.com>
3  *
4  * gstdevice.c: Device discovery
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:gstdevice
24  * @short_description: Object representing a device
25  * @see_also: #GstDeviceProvider
26  *
27  * #GstDevice are objects representing a device, they contain
28  * relevant metadata about the device, such as its class and the #GstCaps
29  * representing the media types it can produce or handle.
30  *
31  * #GstDevice are created by #GstDeviceProvider objects which can be
32  * aggregated by #GstDeviceMonitor objects.
33  *
34  * Since: 1.4
35  */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include "gst_private.h"
42
43 #include "gstdevice.h"
44
45 enum
46 {
47   PROP_DISPLAY_NAME = 1,
48   PROP_CAPS,
49   PROP_DEVICE_CLASS,
50   PROP_PROPERTIES
51 };
52
53 enum
54 {
55   REMOVED,
56   LAST_SIGNAL
57 };
58
59 struct _GstDevicePrivate
60 {
61   GstCaps *caps;
62   gchar *device_class;
63   gchar *display_name;
64   GstStructure *properties;
65 };
66
67
68 static guint signals[LAST_SIGNAL];
69
70 G_DEFINE_ABSTRACT_TYPE (GstDevice, gst_device, GST_TYPE_OBJECT);
71
72 static void gst_device_get_property (GObject * object, guint property_id,
73     GValue * value, GParamSpec * pspec);
74 static void gst_device_set_property (GObject * object, guint property_id,
75     const GValue * value, GParamSpec * pspec);
76 static void gst_device_finalize (GObject * object);
77
78
79 static void
80 gst_device_class_init (GstDeviceClass * klass)
81 {
82   GObjectClass *object_class = G_OBJECT_CLASS (klass);
83
84   g_type_class_add_private (klass, sizeof (GstDevicePrivate));
85
86   object_class->get_property = gst_device_get_property;
87   object_class->set_property = gst_device_set_property;
88   object_class->finalize = gst_device_finalize;
89
90   g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
91       g_param_spec_string ("display-name", "Display Name",
92           "The user-friendly name of the device", "",
93           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
94   g_object_class_install_property (object_class, PROP_CAPS,
95       g_param_spec_boxed ("caps", "Device Caps",
96           "The possible caps of a device", GST_TYPE_CAPS,
97           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
98   g_object_class_install_property (object_class, PROP_DEVICE_CLASS,
99       g_param_spec_string ("device-class", "Device Class",
100           "The Class of the device", "",
101           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
102   g_object_class_install_property (object_class, PROP_PROPERTIES,
103       g_param_spec_boxed ("properties", "Properties",
104           "The extra properties of the device", GST_TYPE_STRUCTURE,
105           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
106
107   signals[REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (klass),
108       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
109 }
110
111 static void
112 gst_device_init (GstDevice * device)
113 {
114   device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, GST_TYPE_DEVICE,
115       GstDevicePrivate);
116 }
117
118 static void
119 gst_device_finalize (GObject * object)
120 {
121   GstDevice *device = GST_DEVICE (object);
122
123   gst_caps_replace (&device->priv->caps, NULL);
124
125   if (device->priv->properties)
126     gst_structure_free (device->priv->properties);
127   g_free (device->priv->display_name);
128   g_free (device->priv->device_class);
129
130   G_OBJECT_CLASS (gst_device_parent_class)->finalize (object);
131 }
132
133 static void
134 gst_device_get_property (GObject * object, guint prop_id,
135     GValue * value, GParamSpec * pspec)
136 {
137   GstDevice *gstdevice;
138
139   gstdevice = GST_DEVICE_CAST (object);
140
141   switch (prop_id) {
142     case PROP_DISPLAY_NAME:
143       g_value_take_string (value, gst_device_get_display_name (gstdevice));
144       break;
145     case PROP_CAPS:
146       if (gstdevice->priv->caps)
147         g_value_take_boxed (value, gst_device_get_caps (gstdevice));
148       break;
149     case PROP_DEVICE_CLASS:
150       g_value_take_string (value, gst_device_get_device_class (gstdevice));
151       break;
152     case PROP_PROPERTIES:
153       if (gstdevice->priv->properties)
154         g_value_take_boxed (value, gst_device_get_properties (gstdevice));
155       break;
156     default:
157       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
158       break;
159   }
160 }
161
162
163 static void
164 gst_device_set_property (GObject * object, guint prop_id,
165     const GValue * value, GParamSpec * pspec)
166 {
167   GstDevice *gstdevice;
168
169   gstdevice = GST_DEVICE_CAST (object);
170
171   switch (prop_id) {
172     case PROP_DISPLAY_NAME:
173       gstdevice->priv->display_name = g_value_dup_string (value);
174       break;
175     case PROP_CAPS:
176       gst_caps_replace (&gstdevice->priv->caps, g_value_get_boxed (value));
177       break;
178     case PROP_DEVICE_CLASS:
179       gstdevice->priv->device_class = g_value_dup_string (value);
180       break;
181     case PROP_PROPERTIES:
182       if (gstdevice->priv->properties)
183         gst_structure_free (gstdevice->priv->properties);
184       gstdevice->priv->properties = g_value_dup_boxed (value);
185       break;
186     default:
187       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
188       break;
189   }
190 }
191
192 /**
193  * gst_device_create_element:
194  * @device: a #GstDevice
195  * @name: (allow-none): name of new element, or %NULL to automatically
196  * create a unique name.
197  *
198  * Creates the element with all of the required parameters set to use
199  * this device.
200  *
201  * Returns: (transfer full): a new #GstElement configured to use this device
202  *
203  * Since: 1.4
204  */
205 GstElement *
206 gst_device_create_element (GstDevice * device, const gchar * name)
207 {
208   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
209
210   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
211
212   if (klass->create_element)
213     return klass->create_element (device, name);
214   else
215     return NULL;
216 }
217
218 /**
219  * gst_device_get_caps:
220  * @device: a #GstDevice
221  *
222  * Getter for the #GstCaps that this device supports.
223  *
224  * Returns: The #GstCaps supported by this device. Unref with
225  * gst_caps_unref() when done.
226  *
227  * Since: 1.4
228  */
229 GstCaps *
230 gst_device_get_caps (GstDevice * device)
231 {
232   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
233
234   if (device->priv->caps)
235     return gst_caps_ref (device->priv->caps);
236   else
237     return NULL;
238 }
239
240 /**
241  * gst_device_get_display_name:
242  * @device: a #GstDevice
243  *
244  * Gets the user-friendly name of the device.
245  *
246  * Returns: The device name. Free with g_free() after use.
247  *
248  * Since: 1.4
249  */
250 gchar *
251 gst_device_get_display_name (GstDevice * device)
252 {
253   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
254
255   return
256       g_strdup (device->priv->display_name ? device->priv->display_name : "");
257 }
258
259 /**
260  * gst_device_get_device_class:
261  * @device: a #GstDevice
262  *
263  * Gets the "class" of a device. This is a "/" separated list of
264  * classes that represent this device. They are a subset of the
265  * classes of the #GstDeviceProvider that produced this device.
266  *
267  * Returns: The device class. Free with g_free() after use.
268  *
269  * Since: 1.4
270  */
271 gchar *
272 gst_device_get_device_class (GstDevice * device)
273 {
274   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
275
276   if (device->priv->device_class != NULL)
277     return g_strdup (device->priv->device_class);
278   else
279     return g_strdup ("");
280 }
281
282 /**
283  * gst_device_get_properties:
284  * @device: a #GstDevice
285  *
286  * Gets the extra properties of a device.
287  *
288  * Returns: The extra properties or %NULL when there are none.
289  *          Free with gst_structure_free() after use.
290  *
291  * Since: 1.6
292  */
293 GstStructure *
294 gst_device_get_properties (GstDevice * device)
295 {
296   g_return_val_if_fail (GST_IS_DEVICE (device), NULL);
297
298   if (device->priv->properties != NULL)
299     return gst_structure_copy (device->priv->properties);
300   else
301     return NULL;
302 }
303
304 /**
305  * gst_device_reconfigure_element:
306  * @device: a #GstDevice
307  * @element: a #GstElement
308  *
309  * Tries to reconfigure an existing element to use the device. If this
310  * function fails, then one must destroy the element and create a new one
311  * using gst_device_create_element().
312  *
313  * Note: This should only be implemented for elements can change their
314  * device in the PLAYING state.
315  *
316  * Returns: %TRUE if the element could be reconfigured to use this device,
317  * %FALSE otherwise.
318  *
319  * Since: 1.4
320  */
321 gboolean
322 gst_device_reconfigure_element (GstDevice * device, GstElement * element)
323 {
324   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
325
326   g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
327
328   if (klass->reconfigure_element)
329     return klass->reconfigure_element (device, element);
330   else
331     return FALSE;
332 }
333
334 /**
335  * gst_device_has_classesv:
336  * @device: a #GstDevice
337  * @classes: (array zero-terminated=1): a %NULL terminated array of classes
338  *   to match, only match if all classes are matched
339  *
340  * Check if @factory matches all of the given classes
341  *
342  * Returns: %TRUE if @device matches.
343  *
344  * Since: 1.4
345  */
346 gboolean
347 gst_device_has_classesv (GstDevice * device, gchar ** classes)
348 {
349   g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
350
351   if (!classes)
352     return TRUE;
353
354   for (; classes[0]; classes++) {
355     const gchar *klass = classes[0];
356     const gchar *found;
357     guint len;
358
359     if (*klass == '\0')
360       continue;
361
362     found = strstr (device->priv->device_class, klass);
363
364     if (!found)
365       return FALSE;
366     if (found != device->priv->device_class && *(found - 1) != '/')
367       return FALSE;
368
369     len = strlen (klass);
370     if (found[len] != 0 && found[len] != '/')
371       return FALSE;
372   }
373
374   return TRUE;
375 }
376
377 /**
378  * gst_device_has_classes:
379  * @device: a #GstDevice
380  * @classes: a "/"-separated list of device classes to match, only match if
381  *  all classes are matched
382  *
383  * Check if @device matches all of the given classes
384  *
385  * Returns: %TRUE if @device matches.
386  *
387  * Since: 1.4
388  */
389 gboolean
390 gst_device_has_classes (GstDevice * device, const gchar * classes)
391 {
392   gchar **classesv;
393   gboolean res;
394
395   g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
396
397   if (!classes)
398     return TRUE;
399
400   classesv = g_strsplit (classes, "/", 0);
401
402   res = gst_device_has_classesv (device, classesv);
403
404   g_strfreev (classesv);
405
406   return res;
407 }