/* GStreamer TagXmpWriter * Copyright (C) 2010 Thiago Santos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * SECTION:gsttagxmpwriter * @title: GstTagXmpWriter * @short_description: Interface for elements that provide XMP serialization * * This interface is implemented by elements that are able to do XMP serialization. Examples for * such elements are #jifmux and #qtmux. * * Applications can use this interface to configure which XMP schemas should be used when serializing * tags into XMP. Schemas are represented by their names, a full list of the supported schemas can be * obtained from gst_tag_xmp_list_schemas(). By default, all schemas are used. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xmpwriter.h" #include #include static GQuark tag_xmp_writer_key; typedef struct { GSList *schemas; GMutex lock; } GstTagXmpWriterData; #define GST_TAG_XMP_WRITER_DATA_LOCK(data) g_mutex_lock(&data->lock) #define GST_TAG_XMP_WRITER_DATA_UNLOCK(data) g_mutex_unlock(&data->lock) GType gst_tag_xmp_writer_get_type (void) { static volatile gsize xmp_config_type = 0; if (g_once_init_enter (&xmp_config_type)) { GType _type; static const GTypeInfo xmp_config_info = { sizeof (GstTagXmpWriterInterface), /* class_size */ NULL, /* base_init */ NULL, /* base_finalize */ NULL, NULL, /* class_finalize */ NULL, /* class_data */ 0, 0, NULL }; _type = g_type_register_static (G_TYPE_INTERFACE, "GstTagXmpWriter", &xmp_config_info, 0); tag_xmp_writer_key = g_quark_from_static_string ("GST_TAG_XMP_WRITER"); g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT); g_once_init_leave (&xmp_config_type, _type); } return xmp_config_type; } static void gst_tag_xmp_writer_data_add_schema_unlocked (GstTagXmpWriterData * data, const gchar * schema) { if (!g_slist_find_custom (data->schemas, schema, (GCompareFunc) strcmp)) { data->schemas = g_slist_prepend (data->schemas, g_strdup (schema)); } } static void gst_tag_xmp_writer_data_add_all_schemas_unlocked (GstTagXmpWriterData * data) { const gchar **schemas; gint i = 0; /* initialize it with all schemas */ schemas = gst_tag_xmp_list_schemas (); while (schemas[i] != NULL) { gst_tag_xmp_writer_data_add_schema_unlocked (data, schemas[i]); i++; } } static void gst_tag_xmp_writer_data_free (gpointer p) { GstTagXmpWriterData *data = (GstTagXmpWriterData *) p; GSList *iter; if (data->schemas) { for (iter = data->schemas; iter; iter = g_slist_next (iter)) { g_free (iter->data); } g_slist_free (data->schemas); } g_mutex_clear (&data->lock); g_slice_free (GstTagXmpWriterData, data); } static GstTagXmpWriterData * gst_tag_xmp_writer_get_data (GstTagXmpWriter * xmpconfig) { GstTagXmpWriterData *data; data = g_object_get_qdata (G_OBJECT (xmpconfig), tag_xmp_writer_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 (xmpconfig), tag_xmp_writer_key); if (!data) { data = g_slice_new (GstTagXmpWriterData); g_mutex_init (&data->lock); data->schemas = NULL; gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); g_object_set_qdata_full (G_OBJECT (xmpconfig), tag_xmp_writer_key, data, gst_tag_xmp_writer_data_free); } g_mutex_unlock (&create_mutex); } return data; } /** * gst_tag_xmp_writer_add_all_schemas: * @config: a #GstTagXmpWriter * * Adds all available XMP schemas to the configuration. Meaning that * all will be used. */ void gst_tag_xmp_writer_add_all_schemas (GstTagXmpWriter * config) { GstTagXmpWriterData *data; g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); GST_TAG_XMP_WRITER_DATA_UNLOCK (data); } /** * gst_tag_xmp_writer_add_schema: * @config: a #GstTagXmpWriter * @schema: the schema to be added * * Adds @schema to the list schemas */ void gst_tag_xmp_writer_add_schema (GstTagXmpWriter * config, const gchar * schema) { GstTagXmpWriterData *data; g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); gst_tag_xmp_writer_data_add_schema_unlocked (data, schema); GST_TAG_XMP_WRITER_DATA_UNLOCK (data); } /** * gst_tag_xmp_writer_has_schema: * @config: a #GstTagXmpWriter * @schema: the schema to test * * Checks if @schema is going to be used * * Returns: %TRUE if it is going to be used */ gboolean gst_tag_xmp_writer_has_schema (GstTagXmpWriter * config, const gchar * schema) { GstTagXmpWriterData *data; gboolean ret = FALSE; GSList *iter; g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), FALSE); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); for (iter = data->schemas; iter; iter = g_slist_next (iter)) { if (strcmp ((const gchar *) iter->data, schema) == 0) { ret = TRUE; break; } } GST_TAG_XMP_WRITER_DATA_UNLOCK (data); return ret; } /** * gst_tag_xmp_writer_remove_schema: * @config: a #GstTagXmpWriter * @schema: the schema to remove * * Removes a schema from the list of schemas to use. Nothing is done if * the schema wasn't in the list */ void gst_tag_xmp_writer_remove_schema (GstTagXmpWriter * config, const gchar * schema) { GstTagXmpWriterData *data; GSList *iter = NULL; g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); for (iter = data->schemas; iter; iter = g_slist_next (iter)) { if (strcmp ((const gchar *) iter->data, schema) == 0) { g_free (iter->data); data->schemas = g_slist_delete_link (data->schemas, iter); break; } } GST_TAG_XMP_WRITER_DATA_UNLOCK (data); } /** * gst_tag_xmp_writer_remove_all_schemas: * @config: a #GstTagXmpWriter * * Removes all schemas from the list of schemas to use. Meaning that no * XMP will be generated. */ void gst_tag_xmp_writer_remove_all_schemas (GstTagXmpWriter * config) { GstTagXmpWriterData *data; GSList *iter; g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); if (data->schemas) { for (iter = data->schemas; iter; iter = g_slist_next (iter)) { g_free (iter->data); } g_slist_free (data->schemas); } data->schemas = NULL; GST_TAG_XMP_WRITER_DATA_UNLOCK (data); } GstBuffer * gst_tag_xmp_writer_tag_list_to_xmp_buffer (GstTagXmpWriter * config, const GstTagList * taglist, gboolean read_only) { GstTagXmpWriterData *data; GstBuffer *buf = NULL; gint i = 0; GSList *iter; g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), NULL); data = gst_tag_xmp_writer_get_data (config); GST_TAG_XMP_WRITER_DATA_LOCK (data); if (data->schemas) { gchar **array = g_new0 (gchar *, g_slist_length (data->schemas) + 1); if (array) { for (iter = data->schemas; iter; iter = g_slist_next (iter)) { array[i++] = (gchar *) iter->data; } buf = gst_tag_list_to_xmp_buffer (taglist, read_only, (const gchar **) array); g_free (array); } } GST_TAG_XMP_WRITER_DATA_UNLOCK (data); return buf; }