2 * Copyright (C) 2010, 2012 Alexander Saprykin <xelfium@gmail.com>
4 * gsttocsetter.c: interface for TOC 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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
23 * SECTION:gsttocsetter
24 * @short_description: Element interface that allows setting and retrieval
27 * Element interface that allows setting of the TOC.
29 * Elements that support some kind of chapters or editions (or tracks like in
30 * the FLAC cue sheet) will implement this interface.
32 * If you just want to retrieve the TOC in your application then all you
33 * need to do is watch for TOC messages on your pipeline's bus (or you can
34 * perform TOC query). This interface is only for setting TOC data, not for
35 * extracting it. To set TOC from the application, find proper tocsetter element
36 * and set TOC using gst_toc_setter_set_toc().
38 * Elements implementing the #GstTocSetter interface can extend existing TOC
39 * by getting extend UID for that (you can use gst_toc_find_entry() to retrieve it)
40 * with any TOC entries received from downstream.
48 #include "gst_private.h"
49 #include "gsttocsetter.h"
50 #include <gobject/gvaluecollector.h>
53 GST_DEBUG_CATEGORY_STATIC (gst_toc_interface_debug);
54 #define GST_CAT_DEFAULT tag_toc_interface_debug
56 static GQuark gst_toc_key;
65 gst_toc_setter_get_type (void)
67 static volatile gsize toc_setter_type = 0;
69 if (g_once_init_enter (&toc_setter_type)) {
71 static const GTypeInfo toc_setter_info = {
72 sizeof (GstTocSetterIFace), /* class_size */
74 NULL, /* base_finalize */
76 NULL, /* class_finalize */
77 NULL, /* class_data */
83 GST_DEBUG_CATEGORY_INIT (gst_toc_interface_debug, "GstTocInterface", 0,
84 "interfaces for the TOC");
86 _type = g_type_register_static (G_TYPE_INTERFACE, "GstTocSetter",
89 g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT);
91 gst_toc_key = g_quark_from_static_string ("GST_TOC_SETTER");
92 g_once_init_leave (&toc_setter_type, _type);
95 return toc_setter_type;
99 gst_toc_data_free (gpointer p)
101 GstTocData *data = (GstTocData *) p;
104 gst_toc_free (data->toc);
106 g_slice_free (GstTocData, data);
110 gst_toc_setter_get_data (GstTocSetter * setter)
114 data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
116 static GMutex create_mutex;
118 /* make sure no other thread is creating a GstTocData at the same time */
119 g_mutex_lock (&create_mutex);
120 data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
122 data = g_slice_new (GstTocData);
123 g_mutex_init (&data->lock);
125 g_object_set_qdata_full (G_OBJECT (setter), gst_toc_key, data,
128 g_mutex_unlock (&create_mutex);
135 * gst_toc_setter_reset_toc:
136 * @setter: a #GstTocSetter.
138 * Reset the internal TOC. Elements should call this from within the
139 * state-change handler.
144 gst_toc_setter_reset_toc (GstTocSetter * setter)
148 g_return_if_fail (GST_IS_TOC_SETTER (setter));
150 data = gst_toc_setter_get_data (setter);
152 g_mutex_lock (&data->lock);
154 gst_toc_free (data->toc);
157 g_mutex_unlock (&data->lock);
161 * gst_toc_setter_get_toc:
162 * @setter: a #GstTocSetter.
164 * Return current TOC the setter uses. The TOC should not be
167 * This function is not thread-safe. Use gst_toc_setter_get_toc_copy() instead.
169 * Returns: a current snapshot of the TOC used in the setter
170 * or NULL if none is used.
175 gst_toc_setter_get_toc (GstTocSetter * setter)
177 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
179 return gst_toc_setter_get_data (setter)->toc;
183 * gst_toc_setter_get_toc_copy:
184 * @setter: a #GstTocSetter.
186 * Return current TOC the setter uses. The difference between this
187 * function and gst_toc_setter_get_toc() is that this function returns deep
188 * copy of the TOC, so you can modify it in any way. This function is thread-safe.
189 * Free it when done with gst_toc_free().
191 * Returns: a copy of the current snapshot of the TOC used in the setter
192 * or NULL if none is used.
197 gst_toc_setter_get_toc_copy (GstTocSetter * setter)
202 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
204 data = gst_toc_setter_get_data (setter);
205 g_mutex_lock (&data->lock);
207 if (data->toc != NULL)
208 ret = gst_toc_copy (data->toc);
210 g_mutex_unlock (&data->lock);
216 * gst_toc_setter_set_toc:
217 * @setter: a #GstTocSetter.
218 * @toc: a #GstToc to set.
220 * Set the given TOC on the setter. Previously setted TOC will be
221 * freed before setting a new one.
226 gst_toc_setter_set_toc (GstTocSetter * setter, const GstToc * toc)
230 g_return_if_fail (GST_IS_TOC_SETTER (setter));
232 data = gst_toc_setter_get_data (setter);
234 g_mutex_lock (&data->lock);
236 gst_toc_free (data->toc);
238 data->toc = gst_toc_copy (toc);
240 g_mutex_unlock (&data->lock);
244 * gst_toc_setter_get_toc_entry:
245 * @setter: a #GstTocSetter.
246 * @uid: UID to find entry with.
248 * Return #GstTocEntry (if any) with given @uid. Returned entry should
249 * not be modified or freed.
251 * This function is not thread-safe. Use gst_toc_setter_get_toc_entry_copy() instead.
253 * Returns: a TOC entry with given @uid from the TOC in the setter
254 * or NULL if none entry with such @uid was found.
259 gst_toc_setter_get_toc_entry (GstTocSetter * setter, const gchar * uid)
262 const GstTocEntry *ret;
264 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
265 g_return_val_if_fail (uid != NULL, NULL);
267 data = gst_toc_setter_get_data (setter);
269 g_mutex_lock (&data->lock);
271 ret = gst_toc_find_entry (data->toc, uid);
273 g_mutex_unlock (&data->lock);
279 * gst_toc_setter_get_toc_entry_copy:
280 * @setter: a #GstTocSetter.
281 * @uid: UID to find entry with.
283 * Return #GstTocEntry (if any) with given @uid. It perform a deep copying,
284 * so you can modify returned value. Free it when done with gst_toc_entry_free().
285 * This function is thread-safe.
287 * Returns: a TOC entry with given @uid from the TOC in the setter
288 * or NULL if none entry with such @uid was found.
293 gst_toc_setter_get_toc_entry_copy (GstTocSetter * setter, const gchar * uid)
296 GstTocEntry *ret = NULL;
297 const GstTocEntry *search;
299 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
300 g_return_val_if_fail (uid != NULL, NULL);
302 data = gst_toc_setter_get_data (setter);
304 g_mutex_lock (&data->lock);
306 search = gst_toc_find_entry (data->toc, uid);
308 ret = gst_toc_entry_copy (search);
310 g_mutex_unlock (&data->lock);
316 * gst_toc_setter_add_toc_entry:
317 * @setter: a #GstTocSetter.
318 * @parent_uid: UID of the parent entry to append given @entry. Use 0 for the TOC root level.
319 * @entry: #GstTocEntry to append.
321 * Try to find entry with given @parent_uid and append an @entry to that #GstTocEntry.
323 * Returns: TRUE if entry with @parent_uid was found, FALSE otherwise.
328 gst_toc_setter_add_toc_entry (GstTocSetter * setter, const gchar * parent_uid,
329 const GstTocEntry * entry)
333 GstTocEntry *copy_entry;
334 gboolean ret = FALSE;
336 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), FALSE);
337 g_return_val_if_fail (parent_uid != NULL, FALSE);
338 g_return_val_if_fail (entry != NULL, FALSE);
340 data = gst_toc_setter_get_data (setter);
342 g_mutex_lock (&data->lock);
344 copy_entry = gst_toc_entry_copy (entry);
346 if (g_strcmp0 (parent_uid, "0") == 0)
347 data->toc->entries = g_list_append (data->toc->entries, copy_entry);
349 parent = gst_toc_find_entry (data->toc, parent_uid);
351 if (parent != NULL) {
352 parent->subentries = g_list_append (parent->subentries, copy_entry);
357 g_mutex_unlock (&data->lock);