gstreamer/ges/ges-meta-container.c
2012-12-19 11:45:38 -03:00

580 lines
17 KiB
C

#include <glib-object.h>
#include <gst/gst.h>
#include "ges-meta-container.h"
/**
* SECTION: ges-metadata-container
* @short_description: An interface for storing metadata
*
* Interface that allows reading and writing metadata
*/
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_meta_container,
G_TYPE_OBJECT, ges_taglist_key =
g_quark_from_static_string ("ges-metadata-container-data"););
static void
ges_meta_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_meta_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;
}
typedef struct
{
GESMetadataForeachFunc func;
const GESMetadataContainer *container;
gpointer data;
} MetadataForeachData;
static void
tag_list_foreach (const GstTagList * taglist, const gchar * tag,
gpointer user_data)
{
MetadataForeachData *data = (MetadataForeachData *) user_data;
GValue value = { 0, };
if (!gst_tag_list_copy_value (&value, taglist, tag))
return;
data->func (data->container, tag, &value, data->data);
}
/**
* ges_metadata_container_foreach:
* @container: container to iterate over
* @func: (scope call): function to be called for each tag
* @user_data: (closure): user specified data
*
* Calls the given function for each tag inside the metadata container. Note
* that if there is no tag, the function won't be called at all.
*/
void
ges_metadata_container_foreach (GESMetadataContainer * container,
GESMetadataForeachFunc func, gpointer user_data)
{
GESMetadata *data;
MetadataForeachData foreach_data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (func != NULL);
data = ges_meta_container_get_data (container);
foreach_data.func = func;
foreach_data.container = container;
foreach_data.data = user_data;
gst_tag_list_foreach (data->list, (GstTagForeachFunc) tag_list_foreach,
&foreach_data);
}
/**
* ges_meta_container_set_boolean:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_boolean (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_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_BOOLEAN);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_int:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_int (GESMetadataContainer * container,
const gchar * metadata_item, gint value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_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);
}
/**
* ges_meta_container_set_uint:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_uint (GESMetadataContainer * container,
const gchar * metadata_item, guint value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_UINT);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_int64:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_int64 (GESMetadataContainer * container,
const gchar * metadata_item, gint64 value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_INT64);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_uint64:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_uint64 (GESMetadataContainer * container,
const gchar * metadata_item, guint64 value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_UINT64);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_float:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_float (GESMetadataContainer * container,
const gchar * metadata_item, gfloat value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_FLOAT);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_double:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_double (GESMetadataContainer * container,
const gchar * metadata_item, gdouble value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_DOUBLE);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_date:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_date (GESMetadataContainer * container,
const gchar * metadata_item, const GDate * value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_DATE);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_date_time:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_container_set_date_time (GESMetadataContainer * container,
const gchar * metadata_item, const GstDateTime * value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, GST_TYPE_DATE_TIME);
gst_tag_list_add (data->list, data->mode, metadata_item, value, NULL);
GES_METADATA_UNLOCK (data);
}
/**
* ges_meta_container_set_string:
* @container: Target container
* @metadata_item: Name of the metadata item to set
* @value: Value to set
* Sets the value of a given metadata item
*/
void
ges_meta_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_meta_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);
}
/**
* ges_meta_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
*/
void
ges_meta_container_set_meta (GESMetadataContainer * container,
const gchar * metadata_item, const GValue * value)
{
GESMetadata *data;
g_return_if_fail (GES_IS_METADATA_CONTAINER (container));
g_return_if_fail (metadata_item != NULL);
data = ges_meta_container_get_data (container);
GES_METADATA_LOCK (data);
ges_metadata_register (metadata_item, G_TYPE_STRING);
gst_tag_list_add_value (data->list, data->mode, metadata_item, value);
GES_METADATA_UNLOCK (data);
}
/**
* ges_metadata_container_to_string:
* @container: a #GESMetadataContainer
*
* Serializes a metadata container to a string.
*
* Returns: a newly-allocated string, or NULL in case of an error. The
* string must be freed with g_free() when no longer needed.
*/
gchar *
ges_metadata_container_to_string (GESMetadataContainer * container)
{
GESMetadata *data;
g_return_val_if_fail (GES_IS_METADATA_CONTAINER (container), NULL);
data = ges_meta_container_get_data (container);
return gst_tag_list_to_string (data->list);
}
/**
* ges_metadata_container_new_from_string:
* @str: a string created with ges_metadata_container_to_string()
*
* Deserializes a metadata container.
*
* Returns: (transfer full): 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) \
gboolean \
ges_meta_container_get_ ## name (GESMetadataContainer *container, \
const gchar *metadata_item, type value) \
{ \
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_meta_container_get_data (container); \
\
return gst_tag_list_get_ ## name (data->list, metadata_item, value); \
}
/**
* ges_meta_container_get_boolean:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (boolean, gboolean *);
/**
* ges_meta_container_get_int:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (int, gint *);
/**
* ges_meta_container_get_uint:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (uint, guint *);
/**
* ges_meta_container_get_int64:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (int64, gint64 *);
/**
* ges_meta_container_get_uint64:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (uint64, guint64 *);
/**
* ges_meta_container_get_float:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (float, gfloat *);
/**
* ges_meta_container_get_double:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (double, gdouble *);
static inline gchar *
_gst_strdup0 (const gchar * s)
{
if (s == NULL || *s == '\0')
return NULL;
return g_strdup (s);
}
/**
* ges_meta_container_get_string:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (string, gchar **);
/**
* ges_meta_container_get_meta:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @value: (out) (transfer full): Destination to which value of metadata item will be copied
*
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*
* Returns: %TRUE if the vale could be optained %FALSE otherwize
*/
gboolean
ges_meta_container_get_meta (GESMetadataContainer * container,
const gchar * tag, GValue * value)
{
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_meta_container_get_data (container);
if (!gst_tag_list_copy_value (value, data->list, tag))
return FALSE;
return (value != NULL);
}
/**
* ges_meta_container_get_date:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (date, GDate **);
/**
* ges_meta_container_get_date_time:
* @container: Target container
* @metadata_item: Name of the metadata item to get
* @dest: (out): Destination to which value of metadata item will be copied
* Gets the value of a given metadata item, returns NULL if @metadata_item
* can not be found.
*/
CREATE_GETTER (date_time, GstDateTime **);