2 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
4 * gsttagsetter.c: interface for tag setting on elements
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
23 * SECTION:gsttagsetter
24 * @title: GstTagsetter
25 * @short_description: Element interface that allows setting and retrieval
28 * Element interface that allows setting of media metadata.
30 * Elements that support changing a stream's metadata will implement this
31 * interface. Examples of such elements are 'vorbisenc', 'theoraenc' and
34 * If you just want to retrieve metadata in your application then all you
35 * need to do is watch for tag messages on your pipeline's bus. This
36 * interface is only for setting metadata, not for extracting it. To set tags
37 * from the application, find tagsetter elements and set tags using e.g.
38 * gst_tag_setter_merge_tags() or gst_tag_setter_add_tags(). Also consider
39 * setting the #GstTagMergeMode that is used for tag events that arrive at the
40 * tagsetter element (default mode is to keep existing tags).
41 * The application should do that before the element goes to %GST_STATE_PAUSED.
43 * Elements implementing the #GstTagSetter interface often have to merge
44 * any tags received from upstream and the tags set by the application via
45 * the interface. This can be done like this:
47 * |[<!-- language="C" -->
48 * GstTagMergeMode merge_mode;
49 * const GstTagList *application_tags;
50 * const GstTagList *event_tags;
51 * GstTagSetter *tagsetter;
54 * tagsetter = GST_TAG_SETTER (element);
56 * merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter);
57 * application_tags = gst_tag_setter_get_tag_list (tagsetter);
58 * event_tags = (const GstTagList *) element->event_tags;
60 * GST_LOG_OBJECT (tagsetter, "merging tags, merge mode = %d", merge_mode);
61 * GST_LOG_OBJECT (tagsetter, "event tags: %" GST_PTR_FORMAT, event_tags);
62 * GST_LOG_OBJECT (tagsetter, "set tags: %" GST_PTR_FORMAT, application_tags);
64 * result = gst_tag_list_merge (application_tags, event_tags, merge_mode);
66 * GST_LOG_OBJECT (tagsetter, "final tags: %" GST_PTR_FORMAT, result);
74 #include "gst_private.h"
75 #include "gsttagsetter.h"
76 #include <gobject/gvaluecollector.h>
79 static GQuark gst_tag_key;
88 #define GST_TAG_DATA_LOCK(data) g_mutex_lock(&data->lock)
89 #define GST_TAG_DATA_UNLOCK(data) g_mutex_unlock(&data->lock)
91 G_DEFINE_INTERFACE_WITH_CODE (GstTagSetter, gst_tag_setter, GST_TYPE_ELEMENT,
92 gst_tag_key = g_quark_from_static_string ("gst-tag-setter-data");
96 gst_tag_setter_default_init (GstTagSetterInterface * klass)
98 /* nothing to do here, it's a dummy interface */
102 gst_tag_data_free (gpointer p)
104 GstTagData *data = (GstTagData *) p;
107 gst_tag_list_unref (data->list);
109 g_mutex_clear (&data->lock);
111 g_slice_free (GstTagData, data);
115 gst_tag_setter_get_data (GstTagSetter * setter)
119 data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
121 /* make sure no other thread is creating a GstTagData at the same time */
122 static GMutex create_mutex; /* no initialisation required */
124 g_mutex_lock (&create_mutex);
126 data = g_object_get_qdata (G_OBJECT (setter), gst_tag_key);
128 data = g_slice_new (GstTagData);
129 g_mutex_init (&data->lock);
131 data->mode = GST_TAG_MERGE_KEEP;
132 g_object_set_qdata_full (G_OBJECT (setter), gst_tag_key, data,
136 g_mutex_unlock (&create_mutex);
143 * gst_tag_setter_reset_tags:
144 * @setter: a #GstTagSetter
146 * Reset the internal taglist. Elements should call this from within the
147 * state-change handler.
150 gst_tag_setter_reset_tags (GstTagSetter * setter)
154 g_return_if_fail (GST_IS_TAG_SETTER (setter));
156 data = gst_tag_setter_get_data (setter);
158 GST_TAG_DATA_LOCK (data);
160 gst_tag_list_unref (data->list);
163 GST_TAG_DATA_UNLOCK (data);
167 * gst_tag_setter_merge_tags:
168 * @setter: a #GstTagSetter
169 * @list: a tag list to merge from
170 * @mode: the mode to merge with
172 * Merges the given list into the setter's list using the given mode.
175 gst_tag_setter_merge_tags (GstTagSetter * setter, const GstTagList * list,
176 GstTagMergeMode mode)
180 g_return_if_fail (GST_IS_TAG_SETTER (setter));
181 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
182 g_return_if_fail (GST_IS_TAG_LIST (list));
184 data = gst_tag_setter_get_data (setter);
186 GST_TAG_DATA_LOCK (data);
187 if (data->list == NULL) {
188 if (mode != GST_TAG_MERGE_KEEP_ALL)
189 data->list = gst_tag_list_copy (list);
191 gst_tag_list_insert (data->list, list, mode);
193 GST_TAG_DATA_UNLOCK (data);
197 * gst_tag_setter_add_tags:
198 * @setter: a #GstTagSetter
199 * @mode: the mode to use
201 * @...: more tag / value pairs to set
203 * Adds the given tag / value pairs on the setter using the given merge mode.
204 * The list must be terminated with %NULL.
207 gst_tag_setter_add_tags (GstTagSetter * setter, GstTagMergeMode mode,
208 const gchar * tag, ...)
212 g_return_if_fail (GST_IS_TAG_SETTER (setter));
213 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
215 va_start (args, tag);
216 gst_tag_setter_add_tag_valist (setter, mode, tag, args);
221 * gst_tag_setter_add_tag_values:
222 * @setter: a #GstTagSetter
223 * @mode: the mode to use
225 * @...: more tag / GValue pairs to set
227 * Adds the given tag / GValue pairs on the setter using the given merge mode.
228 * The list must be terminated with %NULL.
231 gst_tag_setter_add_tag_values (GstTagSetter * setter, GstTagMergeMode mode,
232 const gchar * tag, ...)
236 g_return_if_fail (GST_IS_TAG_SETTER (setter));
237 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
239 va_start (args, tag);
240 gst_tag_setter_add_tag_valist_values (setter, mode, tag, args);
245 * gst_tag_setter_add_tag_valist:
246 * @setter: a #GstTagSetter
247 * @mode: the mode to use
249 * @var_args: tag / value pairs to set
251 * Adds the given tag / value pairs on the setter using the given merge mode.
252 * The list must be terminated with %NULL.
255 gst_tag_setter_add_tag_valist (GstTagSetter * setter, GstTagMergeMode mode,
256 const gchar * tag, va_list var_args)
260 g_return_if_fail (GST_IS_TAG_SETTER (setter));
261 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
263 data = gst_tag_setter_get_data (setter);
265 GST_TAG_DATA_LOCK (data);
267 data->list = gst_tag_list_new_empty ();
269 gst_tag_list_add_valist (data->list, mode, tag, var_args);
271 GST_TAG_DATA_UNLOCK (data);
275 * gst_tag_setter_add_tag_valist_values:
276 * @setter: a #GstTagSetter
277 * @mode: the mode to use
279 * @var_args: tag / GValue pairs to set
281 * Adds the given tag / GValue pairs on the setter using the given merge mode.
282 * The list must be terminated with %NULL.
285 gst_tag_setter_add_tag_valist_values (GstTagSetter * setter,
286 GstTagMergeMode mode, const gchar * tag, va_list var_args)
290 g_return_if_fail (GST_IS_TAG_SETTER (setter));
291 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
293 data = gst_tag_setter_get_data (setter);
295 GST_TAG_DATA_LOCK (data);
298 data->list = gst_tag_list_new_empty ();
300 gst_tag_list_add_valist_values (data->list, mode, tag, var_args);
302 GST_TAG_DATA_UNLOCK (data);
306 * gst_tag_setter_add_tag_value:
307 * @setter: a #GstTagSetter
308 * @mode: the mode to use
310 * @value: GValue to set for the tag
312 * Adds the given tag / GValue pair on the setter using the given merge mode.
315 gst_tag_setter_add_tag_value (GstTagSetter * setter,
316 GstTagMergeMode mode, const gchar * tag, const GValue * value)
320 g_return_if_fail (GST_IS_TAG_SETTER (setter));
321 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
323 data = gst_tag_setter_get_data (setter);
325 GST_TAG_DATA_LOCK (data);
328 data->list = gst_tag_list_new_empty ();
330 gst_tag_list_add_value (data->list, mode, tag, value);
332 GST_TAG_DATA_UNLOCK (data);
336 * gst_tag_setter_get_tag_list:
337 * @setter: a #GstTagSetter
339 * Returns the current list of tags the setter uses. The list should not be
342 * This function is not thread-safe.
344 * Returns: (transfer none) (nullable): a current snapshot of the
345 * taglist used in the setter or %NULL if none is used.
348 gst_tag_setter_get_tag_list (GstTagSetter * setter)
350 g_return_val_if_fail (GST_IS_TAG_SETTER (setter), NULL);
352 return gst_tag_setter_get_data (setter)->list;
356 * gst_tag_setter_set_tag_merge_mode:
357 * @setter: a #GstTagSetter
358 * @mode: The mode with which tags are added
360 * Sets the given merge mode that is used for adding tags from events to tags
361 * specified by this interface. The default is #GST_TAG_MERGE_KEEP, which keeps
362 * the tags set with this interface and discards tags from events.
365 gst_tag_setter_set_tag_merge_mode (GstTagSetter * setter, GstTagMergeMode mode)
369 g_return_if_fail (GST_IS_TAG_SETTER (setter));
370 g_return_if_fail (GST_TAG_MODE_IS_VALID (mode));
372 data = gst_tag_setter_get_data (setter);
374 GST_TAG_DATA_LOCK (data);
376 GST_TAG_DATA_UNLOCK (data);
380 * gst_tag_setter_get_tag_merge_mode:
381 * @setter: a #GstTagSetter
383 * Queries the mode by which tags inside the setter are overwritten by tags
386 * Returns: the merge mode used inside the element.
389 gst_tag_setter_get_tag_merge_mode (GstTagSetter * setter)
391 GstTagMergeMode mode;
394 g_return_val_if_fail (GST_IS_TAG_SETTER (setter), GST_TAG_MERGE_UNDEFINED);
396 data = gst_tag_setter_get_data (setter);
398 GST_TAG_DATA_LOCK (data);
400 GST_TAG_DATA_UNLOCK (data);