Release 1.19.2
[platform/upstream/gst-editing-services.git] / ges / ges-extractable.c
1 /* GStreamer Editing Services
2  *
3  * Copyright (C) 2012 Thibault Saunier <thibault.saunier@collabora.com>
4  * Copyright (C) 2012 Volodymyr Rudyi <vladimir.rudoy@gmail.com>
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  * SECTION: gesextractable
23  * @title: GESExtractable Interface
24  * @short_description: An interface for objects which can be extracted
25  * from a #GESAsset
26  *
27  * A #GObject that implements the #GESExtractable interface can be
28  * extracted from a #GESAsset using ges_asset_extract().
29  *
30  * Each extractable type will have its own way of interpreting the
31  * #GESAsset:id of an asset (or, if it is associated with a specific
32  * subclass of #GESAsset, the asset subclass may handle the
33  * interpretation of the #GESAsset:id). By default, the requested asset
34  * #GESAsset:id will be ignored by a #GESExtractable and will be set to
35  * the type name of the extractable instead. Also by default, when the
36  * requested asset is extracted, the returned object will simply be a
37  * newly created default object of that extractable type. You should check
38  * the documentation for each extractable type to see if they differ from
39  * the default.
40  *
41  * After the object is extracted, it will have a reference to the asset it
42  * came from, which you can retrieve using ges_extractable_get_asset().
43  */
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include "ges-asset.h"
49 #include "ges-internal.h"
50 #include "ges-extractable.h"
51 #include "ges-uri-clip.h"
52
53 static GQuark ges_asset_key;
54
55 G_DEFINE_INTERFACE_WITH_CODE (GESExtractable, ges_extractable,
56     G_TYPE_INITIALLY_UNOWNED,
57     ges_asset_key = g_quark_from_static_string ("ges-extractable-data"));
58
59 static gchar *
60 ges_extractable_check_id_default (GType type, const gchar * id, GError ** error)
61 {
62   return g_strdup (g_type_name (type));
63 }
64
65 static GType
66 ges_extractable_get_real_extractable_type_default (GType type, const gchar * id)
67 {
68   return type;
69 }
70
71 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;       /* Start ignoring GParameter deprecation */
72 static GParameter *
73 extractable_get_parameters_from_id (const gchar * id, guint * n_params)
74 {
75   *n_params = 0;
76
77   return NULL;
78 }
79
80 G_GNUC_END_IGNORE_DEPRECATIONS; /* End ignoring GParameter deprecation */
81 static gchar *
82 extractable_get_id (GESExtractable * self)
83 {
84   GESAsset *asset;
85
86   if ((asset = ges_extractable_get_asset (self)))
87     return g_strdup (ges_asset_get_id (asset));
88
89   return g_strdup (g_type_name (G_OBJECT_TYPE (self)));
90
91 }
92
93 static void
94 ges_extractable_default_init (GESExtractableInterface * iface)
95 {
96   iface->asset_type = GES_TYPE_ASSET;
97   iface->check_id = ges_extractable_check_id_default;
98   iface->get_real_extractable_type =
99       ges_extractable_get_real_extractable_type_default;
100   iface->get_parameters_from_id = extractable_get_parameters_from_id;
101   iface->set_asset = NULL;
102   iface->set_asset_full = NULL;
103   iface->get_id = extractable_get_id;
104   iface->register_metas = NULL;
105   iface->can_update_asset = FALSE;
106 }
107
108 /**
109  * ges_extractable_get_asset:
110  * @self: A #GESExtractable
111  *
112  * Get the asset that has been set on the extractable object.
113  *
114  * Returns: (transfer none) (nullable): The asset set on @self, or %NULL
115  * if no asset has been set.
116  */
117 GESAsset *
118 ges_extractable_get_asset (GESExtractable * self)
119 {
120   g_return_val_if_fail (GES_IS_EXTRACTABLE (self), NULL);
121
122   return g_object_get_qdata (G_OBJECT (self), ges_asset_key);;
123 }
124
125 /**
126  * ges_extractable_set_asset:
127  * @self: A #GESExtractable
128  * @asset: (transfer none): The asset to set
129  *
130  * Sets the asset for this extractable object.
131  *
132  * When an object is extracted from an asset using ges_asset_extract() its
133  * asset will be automatically set. Note that many classes that implement
134  * #GESExtractable will automatically create their objects using assets
135  * when you call their @new methods. However, you can use this method to
136  * associate an object with a compatible asset if it was created by other
137  * means and does not yet have an asset. Or, for some implementations of
138  * #GESExtractable, you can use this to change the asset of the given
139  * extractable object, which will lead to a change in its state to
140  * match the new asset #GESAsset:id.
141  *
142  * Returns: %TRUE if @asset could be successfully set on @self.
143  */
144 gboolean
145 ges_extractable_set_asset (GESExtractable * self, GESAsset * asset)
146 {
147   GESExtractableInterface *iface;
148   GType extract_type;
149
150   g_return_val_if_fail (GES_IS_EXTRACTABLE (self), FALSE);
151
152   iface = GES_EXTRACTABLE_GET_INTERFACE (self);
153   GST_DEBUG_OBJECT (self, "Setting asset to %" GST_PTR_FORMAT, asset);
154
155   if (iface->can_update_asset == FALSE &&
156       g_object_get_qdata (G_OBJECT (self), ges_asset_key)) {
157     GST_WARNING_OBJECT (self, "Can not reset asset on object");
158     /* FIXME: do not fail if the same asset */
159
160     return FALSE;
161   }
162
163   extract_type = ges_asset_get_extractable_type (asset);
164   if (G_OBJECT_TYPE (self) != extract_type) {
165     GST_WARNING_OBJECT (self, "Can not set the asset to %" GST_PTR_FORMAT
166         " because its extractable-type is %s, rather than %s",
167         asset, g_type_name (extract_type), G_OBJECT_TYPE_NAME (self));
168
169     return FALSE;
170   }
171
172   g_object_set_qdata_full (G_OBJECT (self), ges_asset_key,
173       gst_object_ref (asset), gst_object_unref);
174
175   /* Let classes that implement the interface know that a asset has been set */
176   if (iface->set_asset_full)
177     /* FIXME: return to the previous asset if the setting fails */
178     return iface->set_asset_full (self, asset);
179
180   if (iface->set_asset)
181     iface->set_asset (self, asset);
182
183   return TRUE;
184 }
185
186 /**
187  * ges_extractable_get_id:
188  * @self: A #GESExtractable
189  *
190  * Gets the #GESAsset:id of some associated asset. It may be the case
191  * that the object has no set asset, or even that such an asset does not
192  * yet exist in the GES cache. Instead, this will return the asset
193  * #GESAsset:id that is _compatible_ with the current state of the object,
194  * as determined by the #GESExtractable implementer. If it was indeed
195  * extracted from an asset, this should return the same as its
196  * corresponding asset #GESAsset:id.
197  *
198  * Returns: (transfer full): The #GESAsset:id of some associated #GESAsset
199  * that is compatible with @self's current state.
200  */
201 gchar *
202 ges_extractable_get_id (GESExtractable * self)
203 {
204   g_return_val_if_fail (GES_IS_EXTRACTABLE (self), NULL);
205
206   return GES_EXTRACTABLE_GET_INTERFACE (self)->get_id (self);
207 }
208
209 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;       /* Start ignoring GParameter deprecation */
210 /**
211  * ges_extractable_type_get_parameters_for_id:
212  * @type: The #GType implementing #GESExtractable
213  * @id: The ID of the Extractable
214  * @n_params: (out): Return location for the returned array
215  *
216  * Returns: (transfer full) (array length=n_params): an array of #GParameter
217  * needed to extract the #GESExtractable from a #GESAsset of @id
218  */
219 GParameter *
220 ges_extractable_type_get_parameters_from_id (GType type, const gchar * id,
221     guint * n_params)
222 {
223   GObjectClass *klass;
224   GESExtractableInterface *iface;
225
226   GParameter *ret = NULL;
227
228   g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), NULL);
229   g_return_val_if_fail (g_type_is_a (type, GES_TYPE_EXTRACTABLE), NULL);
230
231   klass = g_type_class_ref (type);
232   iface = g_type_interface_peek (klass, GES_TYPE_EXTRACTABLE);
233
234   ret = iface->get_parameters_from_id (id, n_params);
235
236   g_type_class_unref (klass);
237
238   return ret;
239 }
240
241 G_GNUC_END_IGNORE_DEPRECATIONS; /* End ignoring GParameter deprecation */
242
243 /**
244  * ges_extractable_type_get_asset_type:
245  * @type: The #GType implementing #GESExtractable
246  *
247  * Get the #GType, subclass of #GES_TYPE_ASSET to instanciate
248  * to be able to extract a @type
249  *
250  * Returns: the #GType to use to create a asset to extract @type
251  */
252 GType
253 ges_extractable_type_get_asset_type (GType type)
254 {
255   GObjectClass *klass;
256   GESExtractableInterface *iface;
257
258   g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), G_TYPE_INVALID);
259   g_return_val_if_fail (g_type_is_a (type, GES_TYPE_EXTRACTABLE),
260       G_TYPE_INVALID);
261
262   klass = g_type_class_ref (type);
263
264   iface = g_type_interface_peek (klass, GES_TYPE_EXTRACTABLE);
265
266   g_type_class_unref (klass);
267
268   return iface->asset_type;
269 }
270
271 /**
272  * ges_extractable_type_check_id:
273  * @type: The #GType implementing #GESExtractable
274  * @id: The ID to check
275  *
276  * Check if @id is valid for @type
277  *
278  * Returns: (transfer full) (nullable): A newly allocated string containing
279  * the actual ID (after some processing) or %NULL if the ID is wrong.
280  */
281 gchar *
282 ges_extractable_type_check_id (GType type, const gchar * id, GError ** error)
283 {
284   GObjectClass *klass;
285   GESExtractableInterface *iface;
286
287   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
288   g_return_val_if_fail (g_type_is_a (type, G_TYPE_OBJECT), NULL);
289   g_return_val_if_fail (g_type_is_a (type, GES_TYPE_EXTRACTABLE), NULL);
290
291   klass = g_type_class_ref (type);
292
293   iface = g_type_interface_peek (klass, GES_TYPE_EXTRACTABLE);
294
295   g_type_class_unref (klass);
296
297   return iface->check_id (type, id, error);
298 }
299
300 /**
301  * ges_extractable_get_real_extractable_type:
302  * @type: The #GType implementing #GESExtractable
303  * @id: The ID to check
304  *
305  * Get the #GType that should be used as extractable_type for @type and
306  * @id. Usually this will be the same as @type but in some cases they can
307  * be some subclasses of @type. For example, in the case of #GESFormatter,
308  * the returned #GType will be a subclass of #GESFormatter that can be used
309  * to load the file pointed by @id.
310  *
311  * Returns: Return the #GESExtractable type that should be used for @id
312  */
313 GType
314 ges_extractable_get_real_extractable_type_for_id (GType type, const gchar * id)
315 {
316   GType ret;
317   GObjectClass *klass;
318   GESExtractableInterface *iface;
319
320   klass = g_type_class_ref (type);
321   iface = g_type_interface_peek (klass, GES_TYPE_EXTRACTABLE);
322   g_type_class_unref (klass);
323
324   ret = iface->get_real_extractable_type (type, id);
325
326   GST_DEBUG ("Extractable type for id %s and wanted type %s is: %s",
327       id, g_type_name (type), g_type_name (ret));
328
329   return ret;
330 }
331
332 /**
333  * ges_extractable_register_metas:
334  * @self: A #GESExtractable
335  * @asset: The #GESAsset on which metadatas should be registered
336  *
337  * Lets you register standard method for @extractable_type on @asset
338  *
339  * Returns: %TRUE if metas could be register %FALSE otherwize
340  */
341 gboolean
342 ges_extractable_register_metas (GType extractable_type, GESAsset * asset)
343 {
344   GObjectClass *klass;
345   gboolean ret = FALSE;
346   GESExtractableInterface *iface;
347
348   g_return_val_if_fail (g_type_is_a (extractable_type, GES_TYPE_EXTRACTABLE),
349       FALSE);
350
351   klass = g_type_class_ref (extractable_type);
352   iface = g_type_interface_peek (klass, GES_TYPE_EXTRACTABLE);
353
354   if (iface->register_metas)
355     ret = iface->register_metas (iface, klass, asset);
356
357   g_type_class_unref (klass);
358   return ret;
359 }