markerlist: implement GESMarkerList
[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 #include "ges-marker-list.h"
29
30 /**
31 * SECTION: gesmetacontainer
32 * @short_description: An interface for storing meta
33 *
34 * Interface that allows reading and writing meta
35 */
36
37 static GQuark ges_meta_key;
38
39 G_DEFINE_INTERFACE_WITH_CODE (GESMetaContainer, ges_meta_container,
40     G_TYPE_OBJECT, ges_meta_key =
41     g_quark_from_static_string ("ges-meta-container-data"););
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_set_marker_list:
439  * @container: Target container
440  * @meta_item: Name of the meta item to set
441  * @list: (allow-none) (transfer none): List to set
442  *
443  * Associates a marker list with the given meta item
444  *
445  * Return: %TRUE if the meta could be added, %FALSE otherwise
446  * Since: 1.18
447  */
448 gboolean
449 ges_meta_container_set_marker_list (GESMetaContainer * container,
450     const gchar * meta_item, const GESMarkerList * list)
451 {
452   gboolean ret;
453   GValue v = G_VALUE_INIT;
454   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
455   g_return_val_if_fail (meta_item != NULL, FALSE);
456
457   if (list == NULL) {
458     GstStructure *structure = _meta_container_get_structure (container);
459     gst_structure_remove_field (structure, meta_item);
460
461     g_signal_emit (container, _signals[NOTIFY_SIGNAL], 0, meta_item, list);
462
463     return TRUE;
464   }
465
466   g_return_val_if_fail (GES_IS_MARKER_LIST ((gpointer) list), FALSE);
467
468   if (_can_write_value (container, meta_item, GES_TYPE_MARKER_LIST) == FALSE)
469     return FALSE;
470
471   g_value_init_from_instance (&v, (gpointer) list);
472
473   ret = _set_value (container, meta_item, &v);
474
475   g_value_unset (&v);
476
477   return ret;
478 }
479
480 /**
481  * ges_meta_container_metas_to_string:
482  * @container: a #GESMetaContainer
483  *
484  * Serializes a meta container to a string.
485  *
486  * Returns: (nullable): a newly-allocated string, or NULL in case of an error.
487  * The string must be freed with g_free() when no longer needed.
488  */
489 gchar *
490 ges_meta_container_metas_to_string (GESMetaContainer * container)
491 {
492   GstStructure *structure;
493
494   g_return_val_if_fail (GES_IS_META_CONTAINER (container), NULL);
495
496   structure = _meta_container_get_structure (container);
497
498   return gst_structure_to_string (structure);
499 }
500
501 /**
502  * ges_meta_container_add_metas_from_string:
503  * @container: Target container
504  * @str: a string created with ges_meta_container_metas_to_string()
505  *
506  * Deserializes a meta container.
507  *
508  * Returns: TRUE on success, FALSE if there was an error.
509  */
510 gboolean
511 ges_meta_container_add_metas_from_string (GESMetaContainer * container,
512     const gchar * str)
513 {
514   GstStructure *n_structure;
515
516   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
517
518   n_structure = gst_structure_from_string (str, NULL);
519   if (n_structure == NULL) {
520     GST_WARNING_OBJECT (container, "Could not add metas: %s", str);
521     return FALSE;
522   }
523
524   gst_structure_foreach (n_structure, (GstStructureForeachFunc) _append_foreach,
525       container);
526
527   gst_structure_free (n_structure);
528   return TRUE;
529 }
530
531 #define CREATE_REGISTER_STATIC(name, value_ctype, value_gtype, setter_name) \
532 gboolean                                                                      \
533 ges_meta_container_register_meta_ ## name (GESMetaContainer *container,\
534     GESMetaFlag flags, const gchar *meta_item, value_ctype value)             \
535 {                                                                             \
536   gboolean ret;                                                               \
537   GValue gval = { 0 };                                                        \
538                                                                               \
539   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);            \
540   g_return_val_if_fail (meta_item != NULL, FALSE);                            \
541                                                                               \
542   if (!_register_meta (container, flags, meta_item, value_gtype))             \
543     return FALSE;                                                             \
544                                                                               \
545   g_value_init (&gval, value_gtype);                                          \
546   g_value_set_ ##setter_name (&gval, value);                                  \
547                                                                               \
548   ret = _set_value  (container, meta_item, &gval);                            \
549                                                                               \
550   g_value_unset (&gval);                                                      \
551   return ret;                                                                 \
552 }
553
554 /**
555  * ges_meta_container_register_meta_boolean:
556  * @container: Target container
557  * @flags: The #GESMetaFlag to be used
558  * @meta_item: Name of the meta item to set
559  * @value: Value to set
560  *
561  * Sets a static meta on @container. This method lets you define static
562  * metadatas, which means that the type of the registered will be the only
563  * type accepted for this meta on that particular @container.
564  *
565  * Return: %TRUE if the meta could be registered, %FALSE otherwise
566  */
567 CREATE_REGISTER_STATIC (boolean, gboolean, G_TYPE_BOOLEAN, boolean);
568
569 /**
570  * ges_meta_container_register_meta_int:
571  * @container: Target container
572  * @flags: The #GESMetaFlag to be used
573  * @meta_item: Name of the meta item to set
574  * @value: Value to set
575  *
576  * Sets a static meta on @container. This method lets you define static
577  * metadatas, which means that the type of the registered will be the only
578  * type accepted for this meta on that particular @container.
579  *
580  * Return: %TRUE if the meta could be registered, %FALSE otherwise
581  */
582 CREATE_REGISTER_STATIC (int, gint, G_TYPE_INT, int);
583
584 /**
585  * ges_meta_container_register_meta_uint:
586  * @container: Target container
587  * @flags: The #GESMetaFlag to be used
588  * @meta_item: Name of the meta item to set
589  * @value: Value to set
590  *
591  * Sets a static meta on @container. This method lets you define static
592  * metadatas, which means that the type of the registered will be the only
593  * type accepted for this meta on that particular @container.
594  *
595  * Return: %TRUE if the meta could be registered, %FALSE otherwise
596  */
597 CREATE_REGISTER_STATIC (uint, guint, G_TYPE_UINT, uint);
598
599 /**
600  * ges_meta_container_register_meta_int64:
601  * @container: Target container
602  * @flags: The #GESMetaFlag to be used
603  * @meta_item: Name of the meta item to set
604  * @value: Value to set
605  *
606  * Sets a static meta on @container. This method lets you define static
607  * metadatas, which means that the type of the registered will be the only
608  * type accepted for this meta on that particular @container.
609  *
610  * Return: %TRUE if the meta could be registered, %FALSE otherwise
611  */
612 CREATE_REGISTER_STATIC (int64, gint64, G_TYPE_INT64, int64);
613
614 /**
615  * ges_meta_container_register_meta_uint64:
616  * @container: Target container
617  * @flags: The #GESMetaFlag to be used
618  * @meta_item: Name of the meta item to set
619  * @value: Value to set
620  *
621  * Sets a static meta on @container. This method lets you define static
622  * metadatas, which means that the type of the registered will be the only
623  * type accepted for this meta on that particular @container.
624  *
625  * Return: %TRUE if the meta could be registered, %FALSE otherwise
626  */
627 CREATE_REGISTER_STATIC (uint64, guint64, G_TYPE_UINT64, uint64);
628
629 /**
630  * ges_meta_container_register_meta_float:
631  * @container: Target container
632  * @flags: The #GESMetaFlag to be used
633  * @meta_item: Name of the meta item to set
634  * @value: Value to set
635  *
636  * Sets a static meta on @container. This method lets you define static
637  * metadatas, which means that the type of the registered will be the only
638  * type accepted for this meta on that particular @container.
639  *
640  * Return: %TRUE if the meta could be registered, %FALSE otherwise
641 */
642 CREATE_REGISTER_STATIC (float, float, G_TYPE_FLOAT, float);
643
644 /**
645  * ges_meta_container_register_meta_double:
646  * @container: Target container
647  * @flags: The #GESMetaFlag to be used
648  * @meta_item: Name of the meta item to set
649  * @value: Value to set
650  *
651  * Sets a static meta on @container. This method lets you define static
652  * metadatas, which means that the type of the registered will be the only
653  * type accepted for this meta on that particular @container.
654  *
655  * Return: %TRUE if the meta could be registered, %FALSE otherwise
656  */
657 CREATE_REGISTER_STATIC (double, double, G_TYPE_DOUBLE, double);
658
659 /**
660  * ges_meta_container_register_meta_date:
661  * @container: Target container
662  * @flags: The #GESMetaFlag to be used
663  * @meta_item: Name of the meta item to set
664  * @value: (allow-none): Value to set
665  *
666  * Sets a static meta on @container. This method lets you define static
667  * metadatas, which means that the type of the registered will be the only
668  * type accepted for this meta on that particular @container.
669  *
670  * Return: %TRUE if the meta could be registered, %FALSE otherwise
671  */
672 CREATE_REGISTER_STATIC (date, const GDate *, G_TYPE_DATE, boxed);
673
674 /**
675  * ges_meta_container_register_meta_date_time:
676  * @container: Target container
677  * @flags: The #GESMetaFlag to be used
678  * @meta_item: Name of the meta item to set
679  * @value: (allow-none): Value to set
680  *
681  * Sets a static meta on @container. This method lets you define static
682  * metadatas, which means that the type of the registered will be the only
683  * type accepted for this meta on that particular @container.
684  *
685  * Return: %TRUE if the meta could be registered, %FALSE otherwise
686  */
687 CREATE_REGISTER_STATIC (date_time, const GstDateTime *, GST_TYPE_DATE_TIME,
688     boxed);
689
690 /**
691  * ges_meta_container_register_meta_string:
692  * @container: Target container
693  * @flags: The #GESMetaFlag to be used
694  * @meta_item: Name of the meta item to set
695  * @value: (allow-none): Value to set
696  *
697  * Sets a static meta on @container. This method lets you define static
698  * metadatas, which means that the type of the registered will be the only
699  * type accepted for this meta on that particular @container.
700  *
701  * Return: %TRUE if the meta could be registered, %FALSE otherwise
702  */
703 CREATE_REGISTER_STATIC (string, const gchar *, G_TYPE_STRING, string);
704
705 /**
706  * ges_meta_container_register_meta:
707  * @container: Target container
708  * @flags: The #GESMetaFlag to be used
709  * @meta_item: Name of the meta item to set
710  * @value: Value to set
711  *
712  * Sets a static meta on @container. This method lets you define static
713  * metadatas, which means that the type of the registered will be the only
714  * type accepted for this meta on that particular @container.
715  *
716  * Return: %TRUE if the static meta could be added, %FALSE otherwise
717  */
718 gboolean
719 ges_meta_container_register_meta (GESMetaContainer * container,
720     GESMetaFlag flags, const gchar * meta_item, const GValue * value)
721 {
722   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
723   g_return_val_if_fail (meta_item != NULL, FALSE);
724
725   if (!_register_meta (container, flags, meta_item, G_VALUE_TYPE (value)))
726     return FALSE;
727
728   return _set_value (container, meta_item, value);
729 }
730
731 gboolean
732 ges_meta_container_check_meta_registered (GESMetaContainer * container,
733     const gchar * meta_item, GESMetaFlag * flags, GType * type)
734 {
735   ContainerData *data;
736   RegisteredMeta *static_item;
737
738   data = g_object_get_qdata (G_OBJECT (container), ges_meta_key);
739   if (!data)
740     return FALSE;
741
742   static_item = g_hash_table_lookup (data->static_items, meta_item);
743   if (static_item == NULL) {
744     GST_WARNING_OBJECT (container, "Static meta %s has not been registered yet",
745         meta_item);
746
747     return FALSE;
748   }
749
750   if (type)
751     *type = static_item->item_type;
752
753   if (flags)
754     *flags = static_item->flags;
755
756   return TRUE;
757 }
758
759 /* Copied from gsttaglist.c */
760 /***** evil macros to get all the *_get_* functions right *****/
761
762 #define CREATE_GETTER(name,type)                                         \
763 gboolean                                                                 \
764 ges_meta_container_get_ ## name (GESMetaContainer *container,    \
765                            const gchar *meta_item, type value)       \
766 {                                                                        \
767   GstStructure *structure;                                                     \
768                                                                          \
769   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);   \
770   g_return_val_if_fail (meta_item != NULL, FALSE);                   \
771   g_return_val_if_fail (value != NULL, FALSE);                           \
772                                                                          \
773   structure = _meta_container_get_structure (container);                    \
774                                                                          \
775   return gst_structure_get_ ## name (structure, meta_item, value);   \
776 }
777
778 /**
779  * ges_meta_container_get_boolean:
780  * @container: Target container
781  * @meta_item: Name of the meta item to get
782  * @dest: (out): Destination to which value of meta item will be copied
783  *
784  * Gets the value of a given meta item, returns NULL if @meta_item
785  * can not be found.
786  */
787 CREATE_GETTER (boolean, gboolean *);
788
789 /**
790  * ges_meta_container_get_int:
791  * @container: Target container
792  * @meta_item: Name of the meta item to get
793  * @dest: (out): Destination to which value of meta item will be copied
794  *
795  * Gets the value of a given meta item, returns NULL if @meta_item
796  * can not be found.
797  */
798 CREATE_GETTER (int, gint *);
799
800 /**
801  * ges_meta_container_get_uint:
802  * @container: Target container
803  * @meta_item: Name of the meta item to get
804  * @dest: (out): Destination to which value of meta item will be copied
805  *
806  * Gets the value of a given meta item, returns NULL if @meta_item
807  * can not be found.
808  */
809 CREATE_GETTER (uint, guint *);
810
811 /**
812  * ges_meta_container_get_double:
813  * @container: Target container
814  * @meta_item: Name of the meta item to get
815  * @dest: (out): Destination to which value of meta item will be copied
816  *
817  * Gets the value of a given meta item, returns NULL if @meta_item
818  * can not be found.
819  */
820 CREATE_GETTER (double, gdouble *);
821
822 /**
823  * ges_meta_container_get_int64:
824  * @container: Target container
825  * @meta_item: Name of the meta item to get
826  * @dest: (out): Destination to which value of meta item will be copied
827  *
828  * Gets the value of a given meta item, returns %FALSE if @meta_item
829  * can not be found.
830  */
831 gboolean
832 ges_meta_container_get_int64 (GESMetaContainer * container,
833     const gchar * meta_item, gint64 * dest)
834 {
835   GstStructure *structure;
836   const GValue *value;
837
838   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
839   g_return_val_if_fail (meta_item != NULL, FALSE);
840   g_return_val_if_fail (dest != NULL, FALSE);
841
842   structure = _meta_container_get_structure (container);
843
844   value = gst_structure_get_value (structure, meta_item);
845   if (!value || G_VALUE_TYPE (value) != G_TYPE_INT64)
846     return FALSE;
847
848   *dest = g_value_get_int64 (value);
849
850   return TRUE;
851 }
852
853 /**
854  * ges_meta_container_get_uint64:
855  * @container: Target container
856  * @meta_item: Name of the meta item to get
857  * @dest: (out): Destination to which value of meta item will be copied
858  *
859  * Gets the value of a given meta item, returns %FALSE if @meta_item
860  * can not be found.
861  */
862 gboolean
863 ges_meta_container_get_uint64 (GESMetaContainer * container,
864     const gchar * meta_item, guint64 * dest)
865 {
866   GstStructure *structure;
867   const GValue *value;
868
869   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
870   g_return_val_if_fail (meta_item != NULL, FALSE);
871   g_return_val_if_fail (dest != NULL, FALSE);
872
873   structure = _meta_container_get_structure (container);
874
875   value = gst_structure_get_value (structure, meta_item);
876   if (!value || G_VALUE_TYPE (value) != G_TYPE_UINT64)
877     return FALSE;
878
879   *dest = g_value_get_uint64 (value);
880
881   return TRUE;
882 }
883
884 /**
885  * ges_meta_container_get_float:
886  * @container: Target container
887  * @meta_item: Name of the meta item to get
888  * @dest: (out): Destination to which value of meta item will be copied
889  *
890  * Gets the value of a given meta item, returns %FALSE if @meta_item
891  * can not be found.
892  */
893 gboolean
894 ges_meta_container_get_float (GESMetaContainer * container,
895     const gchar * meta_item, gfloat * dest)
896 {
897   GstStructure *structure;
898   const GValue *value;
899
900   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
901   g_return_val_if_fail (meta_item != NULL, FALSE);
902   g_return_val_if_fail (dest != NULL, FALSE);
903
904   structure = _meta_container_get_structure (container);
905
906   value = gst_structure_get_value (structure, meta_item);
907   if (!value || G_VALUE_TYPE (value) != G_TYPE_FLOAT)
908     return FALSE;
909
910   *dest = g_value_get_float (value);
911
912   return TRUE;
913 }
914
915 /**
916  * ges_meta_container_get_string:
917  * @container: Target container
918  * @meta_item: Name of the meta item to get
919  *
920  * Gets the value of a given meta item, returns NULL if @meta_item
921  * can not be found.
922  */
923 const gchar *
924 ges_meta_container_get_string (GESMetaContainer * container,
925     const gchar * meta_item)
926 {
927   GstStructure *structure;
928
929   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
930   g_return_val_if_fail (meta_item != NULL, FALSE);
931
932   structure = _meta_container_get_structure (container);
933
934   return gst_structure_get_string (structure, meta_item);
935 }
936
937 /**
938  * ges_meta_container_get_meta:
939  * @container: Target container
940  * @key: The key name of the meta to retrieve
941  *
942  * Gets the value of a given meta item, returns NULL if @key
943  * can not be found.
944  *
945  * Returns: the #GValue corresponding to the meta with the given @key.
946  */
947 const GValue *
948 ges_meta_container_get_meta (GESMetaContainer * container, const gchar * key)
949 {
950   GstStructure *structure;
951
952   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
953   g_return_val_if_fail (key != NULL, FALSE);
954
955   structure = _meta_container_get_structure (container);
956
957   return gst_structure_get_value (structure, key);
958 }
959
960 /**
961  * ges_meta_container_get_marker_list:
962  * @container: Target container
963  * @key: The key name of the list to retrieve
964  *
965  * Gets the value of a given meta item, returns NULL if @key
966  * can not be found.
967  *
968  * Returns: (transfer full): the #GESMarkerList corresponding to the meta with the given @key.
969  * Since: 1.18
970  */
971 GESMarkerList *
972 ges_meta_container_get_marker_list (GESMetaContainer * container,
973     const gchar * key)
974 {
975   GstStructure *structure;
976   const GValue *v;
977
978   g_return_val_if_fail (GES_IS_META_CONTAINER (container), FALSE);
979   g_return_val_if_fail (key != NULL, FALSE);
980
981   structure = _meta_container_get_structure (container);
982
983   v = gst_structure_get_value (structure, key);
984
985   if (v == NULL) {
986     return NULL;
987   }
988
989   return GES_MARKER_LIST (g_value_dup_object (v));
990 }
991
992 /**
993  * ges_meta_container_get_date:
994  * @container: Target container
995  * @meta_item: Name of the meta item to get
996  * @dest: (out): Destination to which value of meta item will be copied
997  *
998  * Gets the value of a given meta item, returns NULL if @meta_item
999  * can not be found.
1000  */
1001 CREATE_GETTER (date, GDate **);
1002
1003 /**
1004  * ges_meta_container_get_date_time:
1005  * @container: Target container
1006  * @meta_item: Name of the meta item to get
1007  * @dest: (out): Destination to which value of meta item will be copied
1008  *
1009  * Gets the value of a given meta item, returns NULL if @meta_item
1010  * can not be found.
1011  */
1012 CREATE_GETTER (date_time, GstDateTime **);