device: Add "klass" to GstDevices
[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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "gst/gst_private.h"
27
28 #include <gst/gstdevice.h>
29 #include <gst/gst.h>
30
31 enum
32 {
33   PROP_DISPLAY_NAME = 1,
34   PROP_CAPS,
35   PROP_KLASS
36 };
37
38 enum
39 {
40   REMOVED,
41   LAST_SIGNAL
42 };
43
44 struct _GstDevicePrivate
45 {
46   GstCaps *caps;
47   gchar *klass;
48   gchar *display_name;
49 };
50
51
52 static guint signals[LAST_SIGNAL];
53
54 G_DEFINE_ABSTRACT_TYPE (GstDevice, gst_device, GST_TYPE_OBJECT);
55
56 static void gst_device_get_property (GObject * object, guint property_id,
57     GValue * value, GParamSpec * pspec);
58 static void gst_device_set_property (GObject * object, guint property_id,
59     const GValue * value, GParamSpec * pspec);
60 static void gst_device_finalize (GObject * object);
61
62
63 static void
64 gst_device_class_init (GstDeviceClass * klass)
65 {
66   GObjectClass *object_class = G_OBJECT_CLASS (klass);
67
68   g_type_class_add_private (klass, sizeof (GstDevicePrivate));
69
70   object_class->get_property = gst_device_get_property;
71   object_class->set_property = gst_device_set_property;
72   object_class->finalize = gst_device_finalize;
73
74   g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
75       g_param_spec_string ("display-name", "Display Name",
76           "The user-friendly name of the device", "",
77           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
78   g_object_class_install_property (object_class, PROP_CAPS,
79       g_param_spec_boxed ("caps", "Device Caps",
80           "The possible caps of a device", GST_TYPE_CAPS,
81           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
82   g_object_class_install_property (object_class, PROP_KLASS,
83       g_param_spec_string ("klass", "Device Class",
84           "The Class of the device", "",
85           G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
86
87   signals[REMOVED] = g_signal_new ("removed", G_TYPE_FROM_CLASS (klass),
88       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
89 }
90
91 static void
92 gst_device_init (GstDevice * device)
93 {
94   device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device, GST_TYPE_DEVICE,
95       GstDevicePrivate);
96 }
97
98 static void
99 gst_device_finalize (GObject * object)
100 {
101   GstDevice *device = GST_DEVICE (object);
102
103   gst_caps_replace (&device->priv->caps, NULL);
104
105   g_free (device->priv->display_name);
106   g_free (device->priv->klass);
107
108   G_OBJECT_CLASS (gst_device_parent_class)->finalize (object);
109 }
110
111 static void
112 gst_device_get_property (GObject * object, guint prop_id,
113     GValue * value, GParamSpec * pspec)
114 {
115   GstDevice *gstdevice;
116
117   gstdevice = GST_DEVICE_CAST (object);
118
119   switch (prop_id) {
120     case PROP_DISPLAY_NAME:
121       g_value_take_string (value, gst_device_get_display_name (gstdevice));
122       break;
123     case PROP_CAPS:
124       if (gstdevice->priv->caps)
125         g_value_take_boxed (value, gst_device_get_caps (gstdevice));
126       break;
127     case PROP_KLASS:
128       g_value_take_string (value, gst_device_get_klass (gstdevice));
129       break;
130     default:
131       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
132       break;
133   }
134 }
135
136
137 static void
138 gst_device_set_property (GObject * object, guint prop_id,
139     const GValue * value, GParamSpec * pspec)
140 {
141   GstDevice *gstdevice;
142
143   gstdevice = GST_DEVICE_CAST (object);
144
145   switch (prop_id) {
146     case PROP_DISPLAY_NAME:
147       gstdevice->priv->display_name = g_value_dup_string (value);
148       break;
149     case PROP_CAPS:
150       gst_caps_replace (&gstdevice->priv->caps, g_value_get_boxed (value));
151       break;
152     case PROP_KLASS:
153       gstdevice->priv->klass = g_value_dup_string (value);
154       break;
155     default:
156       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157       break;
158   }
159 }
160
161 /**
162  * gst_device_create_element:
163  * @device: a #GstDevice
164  * @name: (allow-none): name of new element, or NULL to automatically
165  * create a unique name.
166  *
167  * Returns: (transfer full): a new #GstElement configured to use this device
168  *
169  * Since: 1.4
170  */
171 GstElement *
172 gst_device_create_element (GstDevice * device, const gchar * name)
173 {
174   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
175
176   if (klass->create_element)
177     return klass->create_element (device, name);
178   else
179     return NULL;
180 }
181
182 /**
183  * gst_device_get_caps:
184  * @device: a #GstDevice
185  *
186  * Getter for the #GstCaps that this device supports.
187  *
188  * Returns: The #GstCaps supported by this device. Unref with
189  * gst_caps_unref() when done.
190  *
191  * Since: 1.4
192  */
193 GstCaps *
194 gst_device_get_caps (GstDevice * device)
195 {
196   if (device->priv->caps)
197     return gst_caps_ref (device->priv->caps);
198   else
199     return NULL;
200 }
201
202 /**
203  * gst_device_get_display_name:
204  * @device: a #GstDevice
205  *
206  * Gets the user-friendly name of the device.
207  *
208  * Returns: The device name. Free with g_free() after use.
209  *
210  * Since: 1.4
211  */
212 gchar *
213 gst_device_get_display_name (GstDevice * device)
214 {
215   return
216       g_strdup (device->priv->display_name ? device->priv->display_name : "");
217 }
218
219 /**
220  * gst_device_get_klass:
221  * @device: a #GstDevice
222  *
223  * Gets the "class" of a device. This is a "/" separated list of
224  * classes that represent this device. They are a subset of the
225  * classes of the #GstDeviceMonitor that produced this device.
226  *
227  * Returns: The device class. Free with g_free() after use.
228  *
229  * Since: 1.4
230  */
231 gchar *
232 gst_device_get_klass (GstDevice * device)
233 {
234   return g_strdup (device->priv->klass ? device->priv->klass : "");
235 }
236
237 /**
238  * gst_device_reconfigure_element:
239  * @device: a #GstDevice
240  * @element: a #GstElement
241  *
242  * Tries to reconfigure an existing element to use the device. If this
243  * function fails, then one must destroy the element and create a new one
244  * using gst_device_create_element().
245  *
246  * Note: This should only be implemented for elements can change their
247  * device in the PLAYING state.
248  *
249  * Returns: %TRUE if the element could be reconfigured to use this device,
250  * %FALSE otherwise.
251  *
252  * Since: 1.4
253  */
254 gboolean
255 gst_device_reconfigure_element (GstDevice * device, GstElement * element)
256 {
257   GstDeviceClass *klass = GST_DEVICE_GET_CLASS (device);
258
259   if (klass->reconfigure_element)
260     return klass->reconfigure_element (device, element);
261   else
262     return FALSE;
263 }
264
265 /**
266  * gst_device_has_classesv:
267  * @device: a #GstDevice
268  * @classes: a %NULL terminated array of klasses to match, only match if all
269  *  classes are matched
270  *
271  * Check if @factory matches all of the given classes
272  *
273  * Returns: %TRUE if @device matches.
274  *
275  * Since: 1.4
276  */
277 gboolean
278 gst_device_has_classesv (GstDevice * device, gchar ** classes)
279 {
280   g_return_val_if_fail (GST_IS_DEVICE (device), FALSE);
281
282
283   for (; classes[0]; classes++) {
284     const gchar *found;
285     guint len;
286
287     if (classes[0] == '\0')
288       continue;
289
290     found = strstr (device->priv->klass, classes[0]);
291
292     if (!found)
293       return FALSE;
294     if (found != device->priv->klass && *(found - 1) != '/')
295       return FALSE;
296
297     len = strlen (classes[0]);
298     if (found[len] != 0 && found[len] != '/')
299       return FALSE;
300   }
301
302   return TRUE;
303 }
304
305 /**
306  * gst_device_has_classes:
307  * @device: a #GstDevice
308  * @classes: a "/" separate list of klasses to match, only match if all classes
309  *  are matched
310  *
311  * Check if @device matches all of the given classes
312  *
313  * Returns: %TRUE if @device matches.
314  *
315  * Since: 1.4
316  */
317 gboolean
318 gst_device_has_classes (GstDevice * device, const gchar * classes)
319 {
320   gchar **classesv;
321   gboolean res;
322
323   classesv = g_strsplit (classes, "/", 0);
324
325   res = gst_device_has_classesv (device, classesv);
326
327   g_strfreev (classesv);
328
329   return res;
330 }