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 (GstTocSetterInterface), /* 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_mutex_clear (&data->lock);
108 g_slice_free (GstTocData, data);
112 gst_toc_setter_get_data (GstTocSetter * setter)
116 data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
118 static GMutex create_mutex;
120 /* make sure no other thread is creating a GstTocData at the same time */
121 g_mutex_lock (&create_mutex);
122 data = g_object_get_qdata (G_OBJECT (setter), gst_toc_key);
124 data = g_slice_new (GstTocData);
125 g_mutex_init (&data->lock);
127 g_object_set_qdata_full (G_OBJECT (setter), gst_toc_key, data,
130 g_mutex_unlock (&create_mutex);
137 * gst_toc_setter_reset_toc:
138 * @setter: a #GstTocSetter.
140 * Reset the internal TOC. Elements should call this from within the
141 * state-change handler.
146 gst_toc_setter_reset_toc (GstTocSetter * setter)
150 g_return_if_fail (GST_IS_TOC_SETTER (setter));
152 data = gst_toc_setter_get_data (setter);
154 g_mutex_lock (&data->lock);
156 gst_toc_free (data->toc);
159 g_mutex_unlock (&data->lock);
163 * gst_toc_setter_get_toc:
164 * @setter: a #GstTocSetter.
166 * Return current TOC the setter uses. The TOC should not be
169 * This function is not thread-safe. Use gst_toc_setter_get_toc_copy() instead.
171 * Returns: a current snapshot of the TOC used in the setter
172 * or NULL if none is used.
177 gst_toc_setter_get_toc (GstTocSetter * setter)
179 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
181 return gst_toc_setter_get_data (setter)->toc;
185 * gst_toc_setter_get_toc_copy:
186 * @setter: a #GstTocSetter.
188 * Return current TOC the setter uses. The difference between this
189 * function and gst_toc_setter_get_toc() is that this function returns deep
190 * copy of the TOC, so you can modify it in any way. This function is thread-safe.
191 * Free it when done with gst_toc_free().
193 * Returns: a copy of the current snapshot of the TOC used in the setter
194 * or NULL if none is used.
199 gst_toc_setter_get_toc_copy (GstTocSetter * setter)
204 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
206 data = gst_toc_setter_get_data (setter);
207 g_mutex_lock (&data->lock);
209 if (data->toc != NULL)
210 ret = gst_toc_copy (data->toc);
212 g_mutex_unlock (&data->lock);
218 * gst_toc_setter_set_toc:
219 * @setter: a #GstTocSetter.
220 * @toc: a #GstToc to set.
222 * Set the given TOC on the setter. Previously setted TOC will be
223 * freed before setting a new one.
228 gst_toc_setter_set_toc (GstTocSetter * setter, const GstToc * toc)
232 g_return_if_fail (GST_IS_TOC_SETTER (setter));
234 data = gst_toc_setter_get_data (setter);
236 g_mutex_lock (&data->lock);
238 gst_toc_free (data->toc);
240 data->toc = gst_toc_copy (toc);
242 g_mutex_unlock (&data->lock);
246 * gst_toc_setter_get_toc_entry:
247 * @setter: a #GstTocSetter.
248 * @uid: UID to find entry with.
250 * Return #GstTocEntry (if any) with given @uid. Returned entry should
251 * not be modified or freed.
253 * This function is not thread-safe. Use gst_toc_setter_get_toc_entry_copy() instead.
255 * Returns: a TOC entry with given @uid from the TOC in the setter
256 * or NULL if none entry with such @uid was found.
261 gst_toc_setter_get_toc_entry (GstTocSetter * setter, const gchar * uid)
264 const GstTocEntry *ret;
266 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
267 g_return_val_if_fail (uid != NULL, NULL);
269 data = gst_toc_setter_get_data (setter);
271 g_mutex_lock (&data->lock);
273 ret = gst_toc_find_entry (data->toc, uid);
275 g_mutex_unlock (&data->lock);
281 * gst_toc_setter_get_toc_entry_copy:
282 * @setter: a #GstTocSetter.
283 * @uid: UID to find entry with.
285 * Return #GstTocEntry (if any) with given @uid. It perform a deep copying,
286 * so you can modify returned value. Free it when done with gst_toc_entry_free().
287 * This function is thread-safe.
289 * Returns: a TOC entry with given @uid from the TOC in the setter
290 * or NULL if none entry with such @uid was found.
295 gst_toc_setter_get_toc_entry_copy (GstTocSetter * setter, const gchar * uid)
298 GstTocEntry *ret = NULL;
299 const GstTocEntry *search;
301 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), NULL);
302 g_return_val_if_fail (uid != NULL, NULL);
304 data = gst_toc_setter_get_data (setter);
306 g_mutex_lock (&data->lock);
308 search = gst_toc_find_entry (data->toc, uid);
310 ret = gst_toc_entry_copy (search);
312 g_mutex_unlock (&data->lock);
318 * gst_toc_setter_add_toc_entry:
319 * @setter: a #GstTocSetter.
320 * @parent_uid: UID of the parent entry to append given @entry. Use 0 for the TOC root level.
321 * @entry: #GstTocEntry to append.
323 * Try to find entry with given @parent_uid and append an @entry to that #GstTocEntry.
325 * Returns: TRUE if entry with @parent_uid was found, FALSE otherwise.
330 gst_toc_setter_add_toc_entry (GstTocSetter * setter, const gchar * parent_uid,
331 const GstTocEntry * entry)
335 GstTocEntry *copy_entry;
336 gboolean ret = FALSE;
338 g_return_val_if_fail (GST_IS_TOC_SETTER (setter), FALSE);
339 g_return_val_if_fail (parent_uid != NULL, FALSE);
340 g_return_val_if_fail (entry != NULL, FALSE);
342 data = gst_toc_setter_get_data (setter);
344 g_mutex_lock (&data->lock);
346 copy_entry = gst_toc_entry_copy (entry);
348 if (g_strcmp0 (parent_uid, "0") == 0)
349 data->toc->entries = g_list_append (data->toc->entries, copy_entry);
351 parent = gst_toc_find_entry (data->toc, parent_uid);
353 if (parent != NULL) {
354 parent->subentries = g_list_append (parent->subentries, copy_entry);
359 g_mutex_unlock (&data->lock);