#include #include #include "ges-metadata-container.h" /** * SECTION: ges-metadata-container * @short_description: An interface for storing metadata * * FIXME: Long description needed */ static GQuark ges_taglist_key; typedef struct { GstTagMergeMode mode; GstTagList *list; GMutex lock; } GESMetadata; #define GES_METADATA_LOCK(data) g_mutex_lock(&data->lock) #define GES_METADATA_UNLOCK(data) g_mutex_unlock(&data->lock) G_DEFINE_INTERFACE_WITH_CODE (GESMetadataContainer, ges_metadata_container, G_TYPE_OBJECT, ges_taglist_key = g_quark_from_static_string ("ges-metadata-container-data"); ); static void ges_metadata_container_default_init (GESMetadataContainerInterface * iface) { } static void ges_metadata_free (gpointer p) { GESMetadata *data = (GESMetadata *) p; if (data->list) gst_tag_list_unref (data->list); g_mutex_clear (&data->lock); g_slice_free (GESMetadata, data); } static GESMetadata * ges_metadata_container_get_data (GESMetadataContainer * container) { GESMetadata *data; data = g_object_get_qdata (G_OBJECT (container), ges_taglist_key); if (!data) { /* make sure no other thread is creating a GstTagData at the same time */ static GMutex create_mutex; /* no initialisation required */ g_mutex_lock (&create_mutex); data = g_object_get_qdata (G_OBJECT (container), ges_taglist_key); if (!data) { data = g_slice_new (GESMetadata); g_mutex_init (&data->lock); data->list = gst_tag_list_new_empty (); data->mode = GST_TAG_MERGE_KEEP; g_object_set_qdata_full (G_OBJECT (container), ges_taglist_key, data, ges_metadata_free); } g_mutex_unlock (&create_mutex); } return data; } /***** evil macros to get all the *_get_* functions right *****/ #define CREATE_SETTER(name,type,gtype) \ void \ ges_metadata_container_set_ ## name (GESMetadataContainer *container, \ const gchar *metadata_item, type value) \ { \ GESMetadata *data; \ \ g_return_if_fail (GES_IS_METADATA_CONTAINER (container)); \ g_return_if_fail (metadata_item != NULL); \ \ data = ges_metadata_container_get_data (container); \ \ GES_METADATA_LOCK (data); \ ges_metadata_register (metadata_item, gtype); \ gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL); \ GES_METADATA_UNLOCK (data); \ } /** * ges_metadata_container_set_value * @container: Target container * @metadata_item: Name of the metadata item to set * @value: Value to set * Sets the value of a given metadata item */ CREATE_SETTER (boolean, gboolean, G_TYPE_BOOLEAN); CREATE_GETTER (int, gint, G_TYPE_INT); /*CREATE_GETTER (uint, guint, G_TYPE_UINT); CREATE_GETTER (int64, gint64, G_TYPE_INT64); CREATE_GETTER (uint64, guint64, G_TYPE_UINT64); CREATE_GETTER (float, gfloat, G_TYPE_FLOAT); CREATE_GETTER (double, gdouble, G_TYPE_DOUBLE);*/ /*void ges_metadata_container_set_int2 (GESMetadataContainer * container, const gchar * metadata_item, gboolean value) { GESMetadata *data; g_return_if_fail (GES_IS_METADATA_CONTAINER (container)); g_return_if_fail (metadata_item != NULL); data = ges_metadata_container_get_data (container); GES_METADATA_LOCK (data); ges_metadata_register (metadata_item, G_TYPE_INT); gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL); GES_METADATA_UNLOCK (data); }*/ void ges_metadata_container_set_date_time (GESMetadataContainer * container, const gchar * metadata_item, const GstDateTime * value) { } void ges_metadata_container_set_string (GESMetadataContainer * container, const gchar * metadata_item, const gchar * value) { GESMetadata *data; g_return_if_fail (GES_IS_METADATA_CONTAINER (container)); g_return_if_fail (metadata_item != NULL); data = ges_metadata_container_get_data (container); GES_METADATA_LOCK (data); ges_metadata_register (metadata_item, G_TYPE_STRING); gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL); GES_METADATA_UNLOCK (data); } void ges_metadata_container_foreach (GESMetadataContainer * container, GESMetadataContainerForeachFunc func, gpointer user_data) { } gchar * ges_metadata_container_to_string (GESMetadataContainer * container) { return NULL; } /** * ges_metadata_container_new_from_string: * @str: a string created with ges_metadata_container_to_string() * * Deserializes a metadata container. * * Returns: a new #GESMetadataContainer, or NULL in case of an error. */ GESMetadataContainer * ges_metadata_container_new_from_string (const gchar * str) { return NULL; } void ges_metadata_register (const gchar * name, GType type) { gst_tag_register (name, GST_TAG_FLAG_META, type, name, name, NULL); } /* Copied from gsttaglist.c */ /***** evil macros to get all the *_get_* functions right *****/ #define CREATE_GETTER(name,type,ret) \ gboolean \ ges_metadata_container_get_ ## name (GESMetadataContainer *container, \ const gchar *metadata_item, type *value) \ { \ GValue v = { 0, }; \ GESMetadata *data; \ \ g_return_val_if_fail (GES_IS_METADATA_CONTAINER (container), FALSE); \ g_return_val_if_fail (metadata_item != NULL, FALSE); \ g_return_val_if_fail (value != NULL, FALSE); \ \ data = ges_metadata_container_get_data (container); \ \ if (!gst_tag_list_copy_value (&v, data->list, metadata_item)) \ return FALSE; \ *value = COPY_FUNC (g_value_get_ ## name (&v)); \ g_value_unset (&v); \ return ret; \ } #define COPY_FUNC /**/ CREATE_GETTER (boolean, gboolean, TRUE); CREATE_GETTER (int, gint, TRUE); CREATE_GETTER (uint, guint, TRUE); CREATE_GETTER (int64, gint64, TRUE); CREATE_GETTER (float, gfloat, TRUE); CREATE_GETTER (double, gdouble, TRUE); CREATE_GETTER (uint64, guint64, TRUE); static inline gchar * _gst_strdup0 (const gchar * s) { if (s == NULL || *s == '\0') return NULL; return g_strdup (s); } #undef COPY_FUNC #define COPY_FUNC _gst_strdup0 CREATE_GETTER (string, gchar *, (*value != NULL)); gboolean ges_metadata_container_get_date (GESMetadataContainer * container, const gchar * tag, GDate ** value) { GValue v = { 0, }; GESMetadata *data; g_return_val_if_fail (GES_IS_METADATA_CONTAINER (container), FALSE); g_return_val_if_fail (tag != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); data = ges_metadata_container_get_data (container); if (!gst_tag_list_copy_value (&v, data->list, tag)) return FALSE; *value = (GDate *) g_value_dup_boxed (&v); g_value_unset (&v); return (*value != NULL); } gboolean ges_metadata_container_get_date_time (GESMetadataContainer * container, const gchar * tag, GstDateTime ** value) { GValue v = { 0, }; GESMetadata *data; g_return_val_if_fail (GES_IS_METADATA_CONTAINER (container), FALSE); g_return_val_if_fail (tag != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); data = ges_metadata_container_get_data (container); if (!gst_tag_list_copy_value (&v, data->list, tag)) return FALSE; g_return_val_if_fail (GST_VALUE_HOLDS_DATE_TIME (&v), FALSE); *value = (GstDateTime *) g_value_dup_boxed (&v); g_value_unset (&v); return (*value != NULL); }