4c37e27ee974ac8f59905abc2a415fe73036a682
[platform/upstream/gst-editing-services.git] / ges / ges-meta-container.c
1 /* GStreamer Editing Services
2  * Copyright (C) 2012 Paul Lange <palango@gmx.de>
3  * Copyright (C) <2014> Thibault Saunier <thibault.saunier@collabora.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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <glib-object.h>
25 #include <gst/gst.h>
26
27 #include "ges-meta-container.h"
28
29 /**
30 * SECTION: gesmetacontainer
31 * @short_description: An interface for storing meta
32 *
33 * Interface that allows reading and writing meta
34 */
35
36 static GQuark ges_meta_key;
37
38 G_DEFINE_INTERFACE_WITH_CODE (GESMetaContainer, ges_meta_container,
39     G_TYPE_OBJECT, ges_meta_key =
40     g_quark_from_static_string ("ges-meta-container-data");
41     );
42
43 enum
44 {
45   NOTIFY_SIGNAL,
46   LAST_SIGNAL
47 };
48
49 static guint _signals[LAST_SIGNAL] = { 0 };
50
51 typedef struct RegisteredMeta
52 {
53   GType item_type;
54   GESMetaFlag flags;
55 } RegisteredMeta;
56
57 typedef struct ContainerData
58 {
59   GstStructure *structure;
60   GHashTable *static_items;
61 } ContainerData;
62
63 static void
64 ges_meta_container_default_init (GESMetaContainerInterface * iface)
65 {
66
67   /**
68    * GESMetaContainer::notify:
69    * @container: a #GESMetaContainer
70    * @prop: the key of the value that changed
71    * @value: the #GValue containing the new value
72    *
73    * The notify signal is used to be notify of changes of values
74    * of some metadatas
75    */
76   _signals[NOTIFY_SIGNAL] =
77       g_signal_new ("notify-meta", G_TYPE_FROM_INTERFACE (iface),
78       G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
79       G_SIGNAL_NO_HOOKS, 0, NULL, NULL, g_cclosure_marshal_generic,
80       G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VALUE);
81 }
82
83 static void
84 _free_meta_container_data (ContainerData * data)
85 {
86   gst_structure_free (data->structure);
87   g_hash_table_unref (data->static_items);
88
89   g_slice_free (ContainerData, data);
90 }
91
92 static void
93 _free_static_item (RegisteredMeta * item)
94 {
95   g_slice_free (RegisteredMeta, item);
96 }
97
98 static ContainerData *
99 _create_container_data (GESMetaContainer * container)
100 {
101   ContainerData *data = g_slice_new (ContainerData);
102   data->structure = gst_structure_new_empty ("metadatas");
103   data->static_items = g_hash_table_new_full (g_str_hash, g_str_equal,
104       g_free, (GDestroyNotify) (GDestroyNotify) _free_static_item);
105   g_object_set_qdata_full (G_OBJECT (container), ges_meta_key, data,
106       (GDestroyNotify) _free_meta_container_data);
107
108   return data;
109 }
110
111 static GstStructure *
112 _meta_container_get_structure (GESMetaContainer * container)
113 {
114   ContainerData *data;
115
116   data = g_object_get_qdata (G_OBJECT (container), ges_meta_key);
117   if (!data)
118     data = _create_container_data (container);
119
120   return data->structure;
121 }
122
123 typedef struct
124 {
125   GESMetaForeachFunc func;
126   const GESMetaContainer *container;
127   gpointer data;
128 } MetadataForeachData;
129
130 static gboolean
131 structure_foreach_wrapper (GQuark field_id, const GValue * value,
132     gpointer user_data)
133 {
134   MetadataForeachData *data = (MetadataForeachData *) user_data;
135
136   data->func (data->container, g_quark_to_string (field_id), value, data->data);
137   return TRUE;
138 }
139
140 static gboolean
141 _append_foreach (GQuark field_id, const GValue * value, GESMetaContainer * self)
142 {
143   ges_meta_container_set_meta (self, g_quark_to_string (field_id), value);
144
145   return TRUE;
146 }
147
148 /**
149  * ges_meta_container_foreach:
150  * @container: container to iterate over
151  * @func: (scope call): function to be called for each metadata
152  * @user_data: (closure): user specified data
153  *
154  * Calls the given function for each metadata inside the meta container. Note
155  * that if there is no metadata, the function won't be called at all.
156  */
157 void
158 ges_meta_container_foreach (GESMetaContainer * container,
159     GESMetaForeachFunc func, gpointer user_data)
160 {
161   GstStructure *structure;
162   MetadataForeachData foreach_data;
163
164   g_return_if_fail (GES_IS_META_CONTAINER (container));
165   g_return_if_fail (func != NULL);
166
167   structure = _meta_container_get_structure (container);
168
169   foreach_data.func = func;
170   foreach_data.container = container;
171   foreach_data.data = user_data;
172
173   gst_structure_foreach (structure,
174       (GstStructureForeachFunc) structure_foreach_wrapper, &foreach_data);
175 }
176
177 /* _can_write_value should have been checked before calling */
178 static gboolean
179 _register_meta (GESMetaContainer * container, GESMetaFlag flags,
180     const gchar * meta_item, GType type)
181 {
182   ContainerData *data;
183   RegisteredMeta *static_item;
184
185   data = g_object_get_qdata (G_OBJECT (container), ges_meta_key);
186   if (!data)
187     data = _create_container_data (container);
188   else if (g_hash_table_lookup (data->static_items, meta_item)) {
189     GST_WARNING_OBJECT (container, "Static meta %s already registered",
190         meta_item);
191
192     return FALSE;
193   }
194
195   static_item = g_slice_new0 (RegisteredMeta);
196   static_item->item_type = type;
197   static_item->flags = flags;
198   g_hash_table_insert (data->static_items, g_strdup (meta_item), static_item);
199
200   return TRUE;
201 }
202
203 static gboolean
204 _set_value (GESMetaContainer * container, const gchar * meta_item,
205     const GValue * value)
206 {
207   GstStructure *structure;
208   gchar *val = gst_value_serialize (value);
209
210   if (val == NULL) {
211     GST_WARNING_OBJECT (container, "Could not set value on item: %s",
212         meta_item);
213
214     g_free (val);
215     return FALSE;
216   }
217
218   structure = _meta_container_get_structure (container);
219
220   GST_DEBUG_OBJECT (container, "Setting meta_item %s value: %s::%s",
221       meta_item, G_VALUE_TYPE_NAME (value), val);
222
223   gst_structure_set_value (structure, meta_item, value);
224   g_signal_emit (container, _signals[NOTIFY_SIGNAL], 0, meta_item, value);
225
226   g_free (val);
227   return TRUE;
228 }
229
230 static gboolean
231 _can_write_value (GESMetaContainer * container, const gchar * item_name,
232     GType type)
233 {
234   ContainerData *data;
235   RegisteredMeta *static_item = NULL;
236
237   data = g_object_get_qdata (G_OBJECT (container), ges_meta_key);
238   if (!data) {
239     _create_container_data (container);
240     return TRUE;
241   }
242
243   static_item = g_hash_table_lookup (data->static_items, item_name);
244
245   if (static_item == NULL)
246     return TRUE;
247
248   if ((static_item->flags & GES_META_WRITABLE) == FALSE) {
249     GST_WARNING_OBJECT (container, "Can not write %s", item_name);
250     return FALSE;
251   }
252
253   if (static_item->item_type != type) {
254     GST_WARNING_OBJECT (container, "Can not set value of type %s on %s "
255         "its type is: %s", g_type_name (static_item->item_type), item_name,
256         g_type_name (type));
257     return FALSE;
258   }
259
260   return TRUE;
261 }
262
263 #define CREATE_SETTER(name, value_ctype, value_gtype,  setter_name)     \
264 gboolean                                                                \
265 ges_meta_container_set_ ## name (GESMetaContainer *container,      \
266                            const gchar *meta_item, value_ctype value)   \
267 {                                                                       \
268   GValue gval = { 0 };                                                  \
269   gboolean ret;                                                         \
270                                                                         \
271   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);      \
272   g_return_val_if_fail (meta_item != NULL, FALSE);                      \
273                                                                         \
274   if (_can_write_value (container, meta_item, value_gtype) == FALSE)    \
275     return FALSE;                                                       \
276                                                                         \
277   g_value_init (&gval, value_gtype);                                    \
278   g_value_set_ ##setter_name (&gval, value);                            \
279                                                                         \
280   ret = _set_value (container, meta_item, &gval);                       \
281   g_value_unset (&gval);                                                \
282   return ret;                                                           \
283 }
284
285 /**
286  * ges_meta_container_set_boolean:
287  * @container: Target container
288  * @meta_item: Name of the meta item to set
289  * @value: Value to set
290  *
291  * Sets the value of a given meta item
292  *
293  * Return: %TRUE if the meta could be added, %FALSE otherwise
294  */
295 CREATE_SETTER (boolean, gboolean, G_TYPE_BOOLEAN, boolean);
296
297 /**
298  * ges_meta_container_set_int:
299  * @container: Target container
300  * @meta_item: Name of the meta item to set
301  * @value: Value to set
302  *
303  * Sets the value of a given meta item
304  *
305  * Return: %TRUE if the meta could be added, %FALSE otherwise
306  */
307 CREATE_SETTER (int, gint, G_TYPE_INT, int);
308
309 /**
310  * ges_meta_container_set_uint:
311  * @container: Target container
312  * @meta_item: Name of the meta item to set
313  * @value: Value to set
314  *
315  * Sets the value of a given meta item
316  *
317  * Return: %TRUE if the meta could be added, %FALSE otherwise
318  */
319 CREATE_SETTER (uint, guint, G_TYPE_UINT, uint);
320
321 /**
322  * ges_meta_container_set_int64:
323  * @container: Target container
324  * @meta_item: Name of the meta item to set
325  * @value: Value to set
326  *
327  * Sets the value of a given meta item
328  *
329  * Return: %TRUE if the meta could be added, %FALSE otherwise
330  */
331 CREATE_SETTER (int64, gint64, G_TYPE_INT64, int64);
332
333 /**
334  * ges_meta_container_set_uint64:
335  * @container: Target container
336  * @meta_item: Name of the meta item to set
337  * @value: Value to set
338  *
339  * Sets the value of a given meta item
340  *
341  * Return: %TRUE if the meta could be added, %FALSE otherwise
342  */
343 CREATE_SETTER (uint64, guint64, G_TYPE_UINT64, uint64);
344
345 /**
346  * ges_meta_container_set_float:
347  * @container: Target container
348  * @meta_item: Name of the meta item to set
349  * @value: Value to set
350  *
351  * Sets the value of a given meta item
352  *
353  * Return: %TRUE if the meta could be added, %FALSE otherwise
354  */
355 CREATE_SETTER (float, float, G_TYPE_FLOAT, float);
356
357 /**
358  * ges_meta_container_set_double:
359  * @container: Target container
360  * @meta_item: Name of the meta item to set
361  * @value: Value to set
362  *
363  * Sets the value of a given meta item
364  *
365  * Return: %TRUE if the meta could be added, %FALSE otherwise
366  */
367 CREATE_SETTER (double, double, G_TYPE_DOUBLE, double);
368
369 /**
370  * ges_meta_container_set_date:
371  * @container: Target container
372  * @meta_item: Name of the meta item to set
373  * @value: Value to set
374  *
375  * Sets the value of a given meta item
376  *
377  * Return: %TRUE if the meta could be added, %FALSE otherwise
378  */
379 CREATE_SETTER (date, const GDate *, G_TYPE_DATE, boxed);
380
381 /**
382  * ges_meta_container_set_date_time:
383  * @container: Target container
384  * @meta_item: Name of the meta item to set
385  * @value: Value to set
386  *
387  * Sets the value of a given meta item
388  *
389  * Return: %TRUE if the meta could be added, %FALSE otherwise
390  */
391 CREATE_SETTER (date_time, const GstDateTime *, GST_TYPE_DATE_TIME, boxed);
392
393 /**
394 * ges_meta_container_set_string:
395 * @container: Target container
396 * @meta_item: Name of the meta item to set
397 * @value: Value to set
398 *
399 * Sets the value of a given meta item
400 *
401 * Return: %TRUE if the meta could be added, %FALSE otherwise
402 */
403 CREATE_SETTER (string, const gchar *, G_TYPE_STRING, string);
404
405 /**
406  * ges_meta_container_set_meta:
407  * @container: Target container
408  * @meta_item: Name of the meta item to set
409  * @value: (allow-none): Value to set
410  *
411  * Sets the value of a given meta item
412  *
413  * Return: %TRUE if the meta could be added, %FALSE otherwise
414  */
415 gboolean
416 ges_meta_container_set_meta (GESMetaContainer * container,
417     const gchar * meta_item, const GValue * value)
418 {
419   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
420   g_return_val_if_fail (meta_item != NULL, FALSE);
421
422   if (value == NULL) {
423     GstStructure *structure = _meta_container_get_structure (container);
424     gst_structure_remove_field (structure, meta_item);
425
426     g_signal_emit (container, _signals[NOTIFY_SIGNAL], 0, meta_item, value);
427
428     return TRUE;
429   }
430
431   if (_can_write_value (container, meta_item, G_VALUE_TYPE (value)) == FALSE)
432     return FALSE;
433
434   return _set_value (container, meta_item, value);
435 }
436
437 /**
438  * ges_meta_container_metas_to_string:
439  * @container: a #GESMetaContainer
440  *
441  * Serializes a meta container to a string.
442  *
443  * Returns: (nullable): a newly-allocated string, or NULL in case of an error.
444  * The string must be freed with g_free() when no longer needed.
445  */
446 gchar *
447 ges_meta_container_metas_to_string (GESMetaContainer * container)
448 {
449   GstStructure *structure;
450
451   g_return_val_if_fail (GES_IS_META_CONTAINER (container), NULL);
452
453   structure = _meta_container_get_structure (container);
454
455   return gst_structure_to_string (structure);
456 }
457
458 /**
459  * ges_meta_container_add_metas_from_string:
460  * @container: Target container
461  * @str: a string created with ges_meta_container_metas_to_string()
462  *
463  * Deserializes a meta container.
464  *
465  * Returns: TRUE on success, FALSE if there was an error.
466  */
467 gboolean
468 ges_meta_container_add_metas_from_string (GESMetaContainer * container,
469     const gchar * str)
470 {
471   GstStructure *n_structure;
472
473   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
474
475   n_structure = gst_structure_from_string (str, NULL);
476   if (n_structure == NULL) {
477     GST_WARNING_OBJECT (container, "Could not add metas: %s", str);
478     return FALSE;
479   }
480
481   gst_structure_foreach (n_structure, (GstStructureForeachFunc) _append_foreach,
482       container);
483
484   gst_structure_free (n_structure);
485   return TRUE;
486 }
487
488 #define CREATE_REGISTER_STATIC(name, value_ctype, value_gtype, setter_name) \
489 gboolean                                                                      \
490 ges_meta_container_register_meta_ ## name (GESMetaContainer *container,\
491     GESMetaFlag flags, const gchar *meta_item, value_ctype value)             \
492 {                                                                             \
493   gboolean ret;                                                               \
494   GValue gval = { 0 };                                                        \
495                                                                               \
496   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);            \
497   g_return_val_if_fail (meta_item != NULL, FALSE);                            \
498                                                                               \
499   if (!_register_meta (container, flags, meta_item, value_gtype))             \
500     return FALSE;                                                             \
501                                                                               \
502   g_value_init (&gval, value_gtype);                                          \
503   g_value_set_ ##setter_name (&gval, value);                                  \
504                                                                               \
505   ret = _set_value  (container, meta_item, &gval);                            \
506                                                                               \
507   g_value_unset (&gval);                                                      \
508   return ret;                                                                 \
509 }
510
511 /**
512  * ges_meta_container_register_meta_boolean:
513  * @container: Target container
514  * @flags: The #GESMetaFlag to be used
515  * @meta_item: Name of the meta item to set
516  * @value: Value to set
517  *
518  * Sets a static meta on @container. This method lets you define static
519  * metadatas, which means that the type of the registered will be the only
520  * type accepted for this meta on that particular @container.
521  *
522  * Return: %TRUE if the meta could be registered, %FALSE otherwise
523  */
524 CREATE_REGISTER_STATIC (boolean, gboolean, G_TYPE_BOOLEAN, boolean);
525
526 /**
527  * ges_meta_container_register_meta_int:
528  * @container: Target container
529  * @flags: The #GESMetaFlag to be used
530  * @meta_item: Name of the meta item to set
531  * @value: Value to set
532  *
533  * Sets a static meta on @container. This method lets you define static
534  * metadatas, which means that the type of the registered will be the only
535  * type accepted for this meta on that particular @container.
536  *
537  * Return: %TRUE if the meta could be registered, %FALSE otherwise
538  */
539 CREATE_REGISTER_STATIC (int, gint, G_TYPE_INT, int);
540
541 /**
542  * ges_meta_container_register_meta_uint:
543  * @container: Target container
544  * @flags: The #GESMetaFlag to be used
545  * @meta_item: Name of the meta item to set
546  * @value: Value to set
547  *
548  * Sets a static meta on @container. This method lets you define static
549  * metadatas, which means that the type of the registered will be the only
550  * type accepted for this meta on that particular @container.
551  *
552  * Return: %TRUE if the meta could be registered, %FALSE otherwise
553  */
554 CREATE_REGISTER_STATIC (uint, guint, G_TYPE_UINT, uint);
555
556 /**
557  * ges_meta_container_register_meta_int64:
558  * @container: Target container
559  * @flags: The #GESMetaFlag to be used
560  * @meta_item: Name of the meta item to set
561  * @value: Value to set
562  *
563  * Sets a static meta on @container. This method lets you define static
564  * metadatas, which means that the type of the registered will be the only
565  * type accepted for this meta on that particular @container.
566  *
567  * Return: %TRUE if the meta could be registered, %FALSE otherwise
568  */
569 CREATE_REGISTER_STATIC (int64, gint64, G_TYPE_INT64, int64);
570
571 /**
572  * ges_meta_container_register_meta_uint64:
573  * @container: Target container
574  * @flags: The #GESMetaFlag to be used
575  * @meta_item: Name of the meta item to set
576  * @value: Value to set
577  *
578  * Sets a static meta on @container. This method lets you define static
579  * metadatas, which means that the type of the registered will be the only
580  * type accepted for this meta on that particular @container.
581  *
582  * Return: %TRUE if the meta could be registered, %FALSE otherwise
583  */
584 CREATE_REGISTER_STATIC (uint64, guint64, G_TYPE_UINT64, uint64);
585
586 /**
587  * ges_meta_container_register_meta_float:
588  * @container: Target container
589  * @flags: The #GESMetaFlag to be used
590  * @meta_item: Name of the meta item to set
591  * @value: Value to set
592  *
593  * Sets a static meta on @container. This method lets you define static
594  * metadatas, which means that the type of the registered will be the only
595  * type accepted for this meta on that particular @container.
596  *
597  * Return: %TRUE if the meta could be registered, %FALSE otherwise
598 */
599 CREATE_REGISTER_STATIC (float, float, G_TYPE_FLOAT, float);
600
601 /**
602  * ges_meta_container_register_meta_double:
603  * @container: Target container
604  * @flags: The #GESMetaFlag to be used
605  * @meta_item: Name of the meta item to set
606  * @value: Value to set
607  *
608  * Sets a static meta on @container. This method lets you define static
609  * metadatas, which means that the type of the registered will be the only
610  * type accepted for this meta on that particular @container.
611  *
612  * Return: %TRUE if the meta could be registered, %FALSE otherwise
613  */
614 CREATE_REGISTER_STATIC (double, double, G_TYPE_DOUBLE, double);
615
616 /**
617  * ges_meta_container_register_meta_date:
618  * @container: Target container
619  * @flags: The #GESMetaFlag to be used
620  * @meta_item: Name of the meta item to set
621  * @value: (allow-none): Value to set
622  *
623  * Sets a static meta on @container. This method lets you define static
624  * metadatas, which means that the type of the registered will be the only
625  * type accepted for this meta on that particular @container.
626  *
627  * Return: %TRUE if the meta could be registered, %FALSE otherwise
628  */
629 CREATE_REGISTER_STATIC (date, const GDate *, G_TYPE_DATE, boxed);
630
631 /**
632  * ges_meta_container_register_meta_date_time:
633  * @container: Target container
634  * @flags: The #GESMetaFlag to be used
635  * @meta_item: Name of the meta item to set
636  * @value: (allow-none): Value to set
637  *
638  * Sets a static meta on @container. This method lets you define static
639  * metadatas, which means that the type of the registered will be the only
640  * type accepted for this meta on that particular @container.
641  *
642  * Return: %TRUE if the meta could be registered, %FALSE otherwise
643  */
644 CREATE_REGISTER_STATIC (date_time, const GstDateTime *, GST_TYPE_DATE_TIME,
645     boxed);
646
647 /**
648  * ges_meta_container_register_meta_string:
649  * @container: Target container
650  * @flags: The #GESMetaFlag to be used
651  * @meta_item: Name of the meta item to set
652  * @value: (allow-none): Value to set
653  *
654  * Sets a static meta on @container. This method lets you define static
655  * metadatas, which means that the type of the registered will be the only
656  * type accepted for this meta on that particular @container.
657  *
658  * Return: %TRUE if the meta could be registered, %FALSE otherwise
659  */
660 CREATE_REGISTER_STATIC (string, const gchar *, G_TYPE_STRING, string);
661
662 /**
663  * ges_meta_container_register_meta:
664  * @container: Target container
665  * @flags: The #GESMetaFlag to be used
666  * @meta_item: Name of the meta item to set
667  * @value: Value to set
668  *
669  * Sets a static meta on @container. This method lets you define static
670  * metadatas, which means that the type of the registered will be the only
671  * type accepted for this meta on that particular @container.
672  *
673  * Return: %TRUE if the static meta could be added, %FALSE otherwise
674  */
675 gboolean
676 ges_meta_container_register_meta (GESMetaContainer * container,
677     GESMetaFlag flags, const gchar * meta_item, const GValue * value)
678 {
679   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
680   g_return_val_if_fail (meta_item != NULL, FALSE);
681
682   if (!_register_meta (container, flags, meta_item, G_VALUE_TYPE (value)))
683     return FALSE;
684
685   return _set_value (container, meta_item, value);
686 }
687
688 gboolean
689 ges_meta_container_check_meta_registered (GESMetaContainer * container,
690     const gchar * meta_item, GESMetaFlag * flags, GType * type)
691 {
692   ContainerData *data;
693   RegisteredMeta *static_item;
694
695   data = g_object_get_qdata (G_OBJECT (container), ges_meta_key);
696   if (!data)
697     return FALSE;
698
699   static_item = g_hash_table_lookup (data->static_items, meta_item);
700   if (static_item == NULL) {
701     GST_WARNING_OBJECT (container, "Static meta %s has not been registered yet",
702         meta_item);
703
704     return FALSE;
705   }
706
707   if (type)
708     *type = static_item->item_type;
709
710   if (flags)
711     *flags = static_item->flags;
712
713   return TRUE;
714 }
715
716 /* Copied from gsttaglist.c */
717 /***** evil macros to get all the *_get_* functions right *****/
718
719 #define CREATE_GETTER(name,type)                                         \
720 gboolean                                                                 \
721 ges_meta_container_get_ ## name (GESMetaContainer *container,    \
722                            const gchar *meta_item, type value)       \
723 {                                                                        \
724   GstStructure *structure;                                                     \
725                                                                          \
726   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);   \
727   g_return_val_if_fail (meta_item != NULL, FALSE);                   \
728   g_return_val_if_fail (value != NULL, FALSE);                           \
729                                                                          \
730   structure = _meta_container_get_structure (container);                    \
731                                                                          \
732   return gst_structure_get_ ## name (structure, meta_item, value);   \
733 }
734
735 /**
736  * ges_meta_container_get_boolean:
737  * @container: Target container
738  * @meta_item: Name of the meta item to get
739  * @dest: (out): Destination to which value of meta item will be copied
740  *
741  * Gets the value of a given meta item, returns NULL if @meta_item
742  * can not be found.
743  */
744 CREATE_GETTER (boolean, gboolean *);
745
746 /**
747  * ges_meta_container_get_int:
748  * @container: Target container
749  * @meta_item: Name of the meta item to get
750  * @dest: (out): Destination to which value of meta item will be copied
751  *
752  * Gets the value of a given meta item, returns NULL if @meta_item
753  * can not be found.
754  */
755 CREATE_GETTER (int, gint *);
756
757 /**
758  * ges_meta_container_get_uint:
759  * @container: Target container
760  * @meta_item: Name of the meta item to get
761  * @dest: (out): Destination to which value of meta item will be copied
762  *
763  * Gets the value of a given meta item, returns NULL if @meta_item
764  * can not be found.
765  */
766 CREATE_GETTER (uint, guint *);
767
768 /**
769  * ges_meta_container_get_double:
770  * @container: Target container
771  * @meta_item: Name of the meta item to get
772  * @dest: (out): Destination to which value of meta item will be copied
773  *
774  * Gets the value of a given meta item, returns NULL if @meta_item
775  * can not be found.
776  */
777 CREATE_GETTER (double, gdouble *);
778
779 /**
780  * ges_meta_container_get_int64:
781  * @container: Target container
782  * @meta_item: Name of the meta item to get
783  * @dest: (out): Destination to which value of meta item will be copied
784  *
785  * Gets the value of a given meta item, returns %FALSE if @meta_item
786  * can not be found.
787  */
788 gboolean
789 ges_meta_container_get_int64 (GESMetaContainer * container,
790     const gchar * meta_item, gint64 * dest)
791 {
792   GstStructure *structure;
793   const GValue *value;
794
795   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
796   g_return_val_if_fail (meta_item != NULL, FALSE);
797   g_return_val_if_fail (dest != NULL, FALSE);
798
799   structure = _meta_container_get_structure (container);
800
801   value = gst_structure_get_value (structure, meta_item);
802   if (!value || G_VALUE_TYPE (value) != G_TYPE_INT64)
803     return FALSE;
804
805   *dest = g_value_get_int64 (value);
806
807   return TRUE;
808 }
809
810 /**
811  * ges_meta_container_get_uint64:
812  * @container: Target container
813  * @meta_item: Name of the meta item to get
814  * @dest: (out): Destination to which value of meta item will be copied
815  *
816  * Gets the value of a given meta item, returns %FALSE if @meta_item
817  * can not be found.
818  */
819 gboolean
820 ges_meta_container_get_uint64 (GESMetaContainer * container,
821     const gchar * meta_item, guint64 * dest)
822 {
823   GstStructure *structure;
824   const GValue *value;
825
826   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
827   g_return_val_if_fail (meta_item != NULL, FALSE);
828   g_return_val_if_fail (dest != NULL, FALSE);
829
830   structure = _meta_container_get_structure (container);
831
832   value = gst_structure_get_value (structure, meta_item);
833   if (!value || G_VALUE_TYPE (value) != G_TYPE_UINT64)
834     return FALSE;
835
836   *dest = g_value_get_uint64 (value);
837
838   return TRUE;
839 }
840
841 /**
842  * ges_meta_container_get_float:
843  * @container: Target container
844  * @meta_item: Name of the meta item to get
845  * @dest: (out): Destination to which value of meta item will be copied
846  *
847  * Gets the value of a given meta item, returns %FALSE if @meta_item
848  * can not be found.
849  */
850 gboolean
851 ges_meta_container_get_float (GESMetaContainer * container,
852     const gchar * meta_item, gfloat * dest)
853 {
854   GstStructure *structure;
855   const GValue *value;
856
857   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
858   g_return_val_if_fail (meta_item != NULL, FALSE);
859   g_return_val_if_fail (dest != NULL, FALSE);
860
861   structure = _meta_container_get_structure (container);
862
863   value = gst_structure_get_value (structure, meta_item);
864   if (!value || G_VALUE_TYPE (value) != G_TYPE_FLOAT)
865     return FALSE;
866
867   *dest = g_value_get_float (value);
868
869   return TRUE;
870 }
871
872 /**
873  * ges_meta_container_get_string:
874  * @container: Target container
875  * @meta_item: Name of the meta item to get
876  *
877  * Gets the value of a given meta item, returns NULL if @meta_item
878  * can not be found.
879  */
880 const gchar *
881 ges_meta_container_get_string (GESMetaContainer * container,
882     const gchar * meta_item)
883 {
884   GstStructure *structure;
885
886   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
887   g_return_val_if_fail (meta_item != NULL, FALSE);
888
889   structure = _meta_container_get_structure (container);
890
891   return gst_structure_get_string (structure, meta_item);
892 }
893
894 /**
895  * ges_meta_container_get_meta:
896  * @container: Target container
897  * @key: The key name of the meta to retrieve
898  *
899  * Gets the value of a given meta item, returns NULL if @key
900  * can not be found.
901  *
902  * Returns: the #GValue corresponding to the meta with the given @key.
903  */
904 const GValue *
905 ges_meta_container_get_meta (GESMetaContainer * container, const gchar * key)
906 {
907   GstStructure *structure;
908
909   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
910   g_return_val_if_fail (key != NULL, FALSE);
911
912   structure = _meta_container_get_structure (container);
913
914   return gst_structure_get_value (structure, key);
915 }
916
917 /**
918  * ges_meta_container_get_date:
919  * @container: Target container
920  * @meta_item: Name of the meta item to get
921  * @dest: (out): Destination to which value of meta item will be copied
922  *
923  * Gets the value of a given meta item, returns NULL if @meta_item
924  * can not be found.
925  */
926 CREATE_GETTER (date, GDate **);
927
928 /**
929  * ges_meta_container_get_date_time:
930  * @container: Target container
931  * @meta_item: Name of the meta item to get
932  * @dest: (out): Destination to which value of meta item will be copied
933  *
934  * Gets the value of a given meta item, returns NULL if @meta_item
935  * can not be found.
936  */
937 CREATE_GETTER (date_time, GstDateTime **);