gst/gstindex.c (gst_index_add_object): Note in the docs that this function is not...
[platform/upstream/gstreamer.git] / gst / gstindex.c
1 /* GStreamer
2  * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/)
3  * Written by Erik Walthinsen <omega@ridgerun.com>
4  *
5  * gstindex.c: Index for mappings and other data
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gstindex
25  * @short_description: Generate indexes on objects
26  * @see_also: #GstIndexFactory
27  *
28  * GstIndex is used to generate a stream index of one or more elements
29  * in a pipeline.
30  */
31
32 #include "gst_private.h"
33
34 #include "gstinfo.h"
35 #include "gstindex.h"
36 #include "gstindexfactory.h"
37 #include "gstmarshal.h"
38 #include "gstregistry.h"
39 /* for constructing an entry name */
40 #include "gstelement.h"
41 #include "gstpad.h"
42
43 /* Index signals and args */
44 enum
45 {
46   ENTRY_ADDED,
47   LAST_SIGNAL
48 };
49
50 enum
51 {
52   ARG_0,
53   ARG_RESOLVER
54       /* FILL ME */
55 };
56
57 static void gst_index_class_init (GstIndexClass * klass);
58 static void gst_index_init (GstIndex * index);
59
60 static void gst_index_set_property (GObject * object, guint prop_id,
61     const GValue * value, GParamSpec * pspec);
62 static void gst_index_get_property (GObject * object, guint prop_id,
63     GValue * value, GParamSpec * pspec);
64
65 static GstIndexGroup *gst_index_group_new (guint groupnum);
66
67 static gboolean gst_index_path_resolver (GstIndex * index, GstObject * writer,
68     gchar ** writer_string, gpointer data);
69 static gboolean gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
70     gchar ** writer_string, gpointer data);
71 static void gst_index_add_entry (GstIndex * index, GstIndexEntry * entry);
72
73 static GstObject *parent_class = NULL;
74 static guint gst_index_signals[LAST_SIGNAL] = { 0 };
75
76 typedef struct
77 {
78   GstIndexResolverMethod method;
79   GstIndexResolver resolver;
80   gpointer user_data;
81 }
82 ResolverEntry;
83
84 static const ResolverEntry resolvers[] = {
85   {GST_INDEX_RESOLVER_CUSTOM, NULL, NULL},
86   {GST_INDEX_RESOLVER_GTYPE, gst_index_gtype_resolver, NULL},
87   {GST_INDEX_RESOLVER_PATH, gst_index_path_resolver, NULL},
88 };
89
90 #define GST_TYPE_INDEX_RESOLVER (gst_index_resolver_get_type())
91 static GType
92 gst_index_resolver_get_type (void)
93 {
94   static GType index_resolver_type = 0;
95   static GEnumValue index_resolver[] = {
96     {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM",
97         "Use a custom resolver"},
98     {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE",
99         "Resolve an object to its GType[.padname]"},
100     {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH",
101         "Resolve an object to its path in the pipeline"},
102     {0, NULL, NULL},
103   };
104
105   if (!index_resolver_type) {
106     index_resolver_type =
107         g_enum_register_static ("GstIndexResolver", index_resolver);
108   }
109   return index_resolver_type;
110 }
111
112 GType
113 gst_index_entry_get_type (void)
114 {
115   static GType index_entry_type = 0;
116
117   if (!index_entry_type) {
118     index_entry_type = g_boxed_type_register_static ("GstIndexEntry",
119         (GBoxedCopyFunc) gst_index_entry_copy,
120         (GBoxedFreeFunc) gst_index_entry_free);
121   }
122   return index_entry_type;
123 }
124
125
126 GType
127 gst_index_get_type (void)
128 {
129   static GType index_type = 0;
130
131   if (!index_type) {
132     static const GTypeInfo index_info = {
133       sizeof (GstIndexClass),
134       NULL,
135       NULL,
136       (GClassInitFunc) gst_index_class_init,
137       NULL,
138       NULL,
139       sizeof (GstIndex),
140       0,
141       (GInstanceInitFunc) gst_index_init,
142       NULL
143     };
144
145     index_type =
146         g_type_register_static (GST_TYPE_OBJECT, "GstIndex", &index_info, 0);
147   }
148   return index_type;
149 }
150
151 static void
152 gst_index_class_init (GstIndexClass * klass)
153 {
154   GObjectClass *gobject_class;
155   GstElementClass *gstelement_class;
156
157   gobject_class = (GObjectClass *) klass;
158   gstelement_class = (GstElementClass *) klass;
159
160   parent_class = g_type_class_ref (GST_TYPE_OBJECT);
161
162   /**
163    * GstIndex::entry-added
164    * @gstindex: the object which received the signal.
165    * @arg1: The entry added to the index.
166    *
167    * Is emitted when a new entry is added to the index.
168    */
169   gst_index_signals[ENTRY_ADDED] =
170       g_signal_new ("entry-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
171       G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL,
172       gst_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY);
173
174   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_index_set_property);
175   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_index_get_property);
176
177   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_RESOLVER,
178       g_param_spec_enum ("resolver", "Resolver",
179           "Select a predefined object to string mapper",
180           GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH, G_PARAM_READWRITE));
181 }
182
183 static void
184 gst_index_init (GstIndex * index)
185 {
186   index->curgroup = gst_index_group_new (0);
187   index->maxgroup = 0;
188   index->groups = g_list_prepend (NULL, index->curgroup);
189
190   index->writers = g_hash_table_new (NULL, NULL);
191   index->last_id = 0;
192
193   index->method = GST_INDEX_RESOLVER_PATH;
194   index->resolver = resolvers[index->method].resolver;
195   index->resolver_user_data = resolvers[index->method].user_data;
196
197   GST_OBJECT_FLAG_SET (index, GST_INDEX_WRITABLE);
198   GST_OBJECT_FLAG_SET (index, GST_INDEX_READABLE);
199
200   GST_DEBUG ("created new index");
201 }
202
203 static void
204 gst_index_set_property (GObject * object, guint prop_id,
205     const GValue * value, GParamSpec * pspec)
206 {
207   GstIndex *index;
208
209   index = GST_INDEX (object);
210
211   switch (prop_id) {
212     case ARG_RESOLVER:
213       index->method = g_value_get_enum (value);
214       index->resolver = resolvers[index->method].resolver;
215       index->resolver_user_data = resolvers[index->method].user_data;
216       break;
217     default:
218       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
219       break;
220   }
221 }
222
223 static void
224 gst_index_get_property (GObject * object, guint prop_id,
225     GValue * value, GParamSpec * pspec)
226 {
227   GstIndex *index;
228
229   index = GST_INDEX (object);
230
231   switch (prop_id) {
232     case ARG_RESOLVER:
233       g_value_set_enum (value, index->method);
234       break;
235     default:
236       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
237       break;
238   }
239 }
240
241 static GstIndexGroup *
242 gst_index_group_new (guint groupnum)
243 {
244   GstIndexGroup *indexgroup = g_new (GstIndexGroup, 1);
245
246   indexgroup->groupnum = groupnum;
247   indexgroup->entries = NULL;
248   indexgroup->certainty = GST_INDEX_UNKNOWN;
249   indexgroup->peergroup = -1;
250
251   GST_DEBUG ("created new index group %d", groupnum);
252
253   return indexgroup;
254 }
255
256 /**
257  * gst_index_new:
258  *
259  * Create a new tileindex object
260  *
261  * Returns: a new index object
262  */
263 GstIndex *
264 gst_index_new (void)
265 {
266   GstIndex *index;
267
268   index = g_object_new (gst_index_get_type (), NULL);
269
270   return index;
271 }
272
273 /**
274  * gst_index_commit:
275  * @index: the index to commit
276  * @id: the writer that commited the index
277  *
278  * Tell the index that the writer with the given id is done
279  * with this index and is not going to write any more entries
280  * to it.
281  */
282 void
283 gst_index_commit (GstIndex * index, gint id)
284 {
285   GstIndexClass *iclass;
286
287   iclass = GST_INDEX_GET_CLASS (index);
288
289   if (iclass->commit)
290     iclass->commit (index, id);
291 }
292
293
294 /**
295  * gst_index_get_group:
296  * @index: the index to get the current group from
297  *
298  * Get the id of the current group.
299  *
300  * Returns: the id of the current group.
301  */
302 gint
303 gst_index_get_group (GstIndex * index)
304 {
305   return index->curgroup->groupnum;
306 }
307
308 /**
309  * gst_index_new_group:
310  * @index: the index to create the new group in
311  *
312  * Create a new group for the given index. It will be
313  * set as the current group.
314  *
315  * Returns: the id of the newly created group.
316  */
317 gint
318 gst_index_new_group (GstIndex * index)
319 {
320   index->curgroup = gst_index_group_new (++index->maxgroup);
321   index->groups = g_list_append (index->groups, index->curgroup);
322   GST_DEBUG ("created new group %d in index", index->maxgroup);
323   return index->maxgroup;
324 }
325
326 /**
327  * gst_index_set_group:
328  * @index: the index to set the new group in
329  * @groupnum: the groupnumber to set
330  *
331  * Set the current groupnumber to the given argument.
332  *
333  * Returns: TRUE if the operation succeeded, FALSE if the group
334  * did not exist.
335  */
336 gboolean
337 gst_index_set_group (GstIndex * index, gint groupnum)
338 {
339   GList *list;
340   GstIndexGroup *indexgroup;
341
342   /* first check for null change */
343   if (groupnum == index->curgroup->groupnum)
344     return TRUE;
345
346   /* else search for the proper group */
347   list = index->groups;
348   while (list) {
349     indexgroup = (GstIndexGroup *) (list->data);
350     list = g_list_next (list);
351     if (indexgroup->groupnum == groupnum) {
352       index->curgroup = indexgroup;
353       GST_DEBUG ("switched to index group %d", indexgroup->groupnum);
354       return TRUE;
355     }
356   }
357
358   /* couldn't find the group in question */
359   GST_DEBUG ("couldn't find index group %d", groupnum);
360   return FALSE;
361 }
362
363 /**
364  * gst_index_set_certainty:
365  * @index: the index to set the certainty on
366  * @certainty: the certainty to set
367  *
368  * Set the certainty of the given index.
369  */
370 void
371 gst_index_set_certainty (GstIndex * index, GstIndexCertainty certainty)
372 {
373   index->curgroup->certainty = certainty;
374 }
375
376 /**
377  * gst_index_get_certainty:
378  * @index: the index to get the certainty of
379  *
380  * Get the certainty of the given index.
381  *
382  * Returns: the certainty of the index.
383  */
384 GstIndexCertainty
385 gst_index_get_certainty (GstIndex * index)
386 {
387   return index->curgroup->certainty;
388 }
389
390 /**
391  * gst_index_set_filter:
392  * @index: the index to register the filter on
393  * @filter: the filter to register
394  * @user_data: data passed to the filter function
395  *
396  * Lets the app register a custom filter function so that
397  * it can select what entries should be stored in the index.
398  */
399 void
400 gst_index_set_filter (GstIndex * index,
401     GstIndexFilter filter, gpointer user_data)
402 {
403   g_return_if_fail (GST_IS_INDEX (index));
404
405   index->filter = filter;
406   index->filter_user_data = user_data;
407 }
408
409 /**
410  * gst_index_set_resolver:
411  * @index: the index to register the resolver on
412  * @resolver: the resolver to register
413  * @user_data: data passed to the resolver function
414  *
415  * Lets the app register a custom function to map index
416  * ids to writer descriptions.
417  */
418 void
419 gst_index_set_resolver (GstIndex * index,
420     GstIndexResolver resolver, gpointer user_data)
421 {
422   g_return_if_fail (GST_IS_INDEX (index));
423
424   index->resolver = resolver;
425   index->resolver_user_data = user_data;
426   index->method = GST_INDEX_RESOLVER_CUSTOM;
427 }
428
429 /**
430  * gst_index_entry_copy:
431  * @entry: the entry to copy
432  *
433  * Copies an entry and returns the result.
434  *
435  * Returns: a newly allocated #GstIndexEntry.
436  */
437 GstIndexEntry *
438 gst_index_entry_copy (GstIndexEntry * entry)
439 {
440   return g_memdup (entry, sizeof (*entry));
441 }
442
443 /**
444  * gst_index_entry_free:
445  * @entry: the entry to free
446  *
447  * Free the memory used by the given entry.
448  */
449 void
450 gst_index_entry_free (GstIndexEntry * entry)
451 {
452   g_free (entry);
453 }
454
455 /**
456  * gst_index_add_format:
457  * @index: the index to add the entry to
458  * @id: the id of the index writer
459  * @format: the format to add to the index
460  *
461  * Adds a format entry into the index. This function is
462  * used to map dynamic GstFormat ids to their original
463  * format key.
464  *
465  * Returns: a pointer to the newly added entry in the index.
466  */
467 GstIndexEntry *
468 gst_index_add_format (GstIndex * index, gint id, GstFormat format)
469 {
470   GstIndexEntry *entry;
471   const GstFormatDefinition *def;
472
473   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
474   g_return_val_if_fail (format != 0, NULL);
475
476   if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
477     return NULL;
478
479   entry = g_new0 (GstIndexEntry, 1);
480   entry->type = GST_INDEX_ENTRY_FORMAT;
481   entry->id = id;
482   entry->data.format.format = format;
483
484   def = gst_format_get_details (format);
485   entry->data.format.key = def->nick;
486
487   gst_index_add_entry (index, entry);
488
489   return entry;
490 }
491
492 /**
493  * gst_index_add_id:
494  * @index: the index to add the entry to
495  * @id: the id of the index writer
496  * @description: the description of the index writer
497  *
498  * Add an id entry into the index.
499  *
500  * Returns: a pointer to the newly added entry in the index.
501  */
502 GstIndexEntry *
503 gst_index_add_id (GstIndex * index, gint id, gchar * description)
504 {
505   GstIndexEntry *entry;
506
507   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
508   g_return_val_if_fail (description != NULL, NULL);
509
510   if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
511     return NULL;
512
513   entry = g_new0 (GstIndexEntry, 1);
514   entry->type = GST_INDEX_ENTRY_ID;
515   entry->id = id;
516   entry->data.id.description = description;
517
518   gst_index_add_entry (index, entry);
519
520   return entry;
521 }
522
523 static gboolean
524 gst_index_path_resolver (GstIndex * index, GstObject * writer,
525     gchar ** writer_string, gpointer data)
526 {
527   *writer_string = gst_object_get_path_string (writer);
528
529   return TRUE;
530 }
531
532 static gboolean
533 gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
534     gchar ** writer_string, gpointer data)
535 {
536   if (GST_IS_PAD (writer)) {
537     GstElement *element =
538         (GstElement *) gst_object_get_parent (GST_OBJECT (writer));
539
540     *writer_string = g_strdup_printf ("%s.%s",
541         g_type_name (G_OBJECT_TYPE (element)), gst_object_get_name (writer));
542   } else {
543     *writer_string =
544         g_strdup_printf ("%s", g_type_name (G_OBJECT_TYPE (writer)));
545   }
546
547   return TRUE;
548 }
549
550 /**
551  * gst_index_get_writer_id:
552  * @index: the index to get a unique write id for
553  * @writer: the GstObject to allocate an id for
554  * @id: a pointer to a gint to hold the id
555  *
556  * Before entries can be added to the index, a writer
557  * should obtain a unique id. The methods to add new entries
558  * to the index require this id as an argument.
559  *
560  * The application can implement a custom function to map the writer object
561  * to a string. That string will be used to register or look up an id
562  * in the index.
563  *
564  * Returns: TRUE if the writer would be mapped to an id.
565  */
566 gboolean
567 gst_index_get_writer_id (GstIndex * index, GstObject * writer, gint * id)
568 {
569   gchar *writer_string = NULL;
570   GstIndexEntry *entry;
571   GstIndexClass *iclass;
572   gboolean success = FALSE;
573
574   g_return_val_if_fail (GST_IS_INDEX (index), FALSE);
575   g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE);
576   g_return_val_if_fail (id, FALSE);
577
578   *id = -1;
579
580   /* first try to get a previously cached id */
581   entry = g_hash_table_lookup (index->writers, writer);
582   if (entry == NULL) {
583
584     iclass = GST_INDEX_GET_CLASS (index);
585
586     /* let the app make a string */
587     if (index->resolver) {
588       gboolean res;
589
590       res =
591           index->resolver (index, writer, &writer_string,
592           index->resolver_user_data);
593       if (!res)
594         return FALSE;
595     } else {
596       g_warning ("no resolver found");
597       return FALSE;
598     }
599
600     /* if the index has a resolver, make it map this string to an id */
601     if (iclass->get_writer_id) {
602       success = iclass->get_writer_id (index, id, writer_string);
603     }
604     /* if the index could not resolve, we allocate one ourselves */
605     if (!success) {
606       *id = ++index->last_id;
607     }
608
609     entry = gst_index_add_id (index, *id, writer_string);
610     if (!entry) {
611       /* index is probably not writable, make an entry anyway
612        * to keep it in our cache */
613       entry = g_new0 (GstIndexEntry, 1);
614       entry->type = GST_INDEX_ENTRY_ID;
615       entry->id = *id;
616       entry->data.id.description = writer_string;
617     }
618     g_hash_table_insert (index->writers, writer, entry);
619   } else {
620     *id = entry->id;
621   }
622
623   return TRUE;
624 }
625
626 static void
627 gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
628 {
629   GstIndexClass *iclass;
630
631   iclass = GST_INDEX_GET_CLASS (index);
632
633   if (iclass->add_entry) {
634     iclass->add_entry (index, entry);
635   }
636
637   g_signal_emit (G_OBJECT (index), gst_index_signals[ENTRY_ADDED], 0, entry);
638 }
639
640 /**
641  * gst_index_add_associationv:
642  * @index: the index to add the entry to
643  * @id: the id of the index writer
644  * @flags: optinal flags for this entry
645  * @n: number of associations
646  * @list: list of associations
647  * @...: other format/value pairs or 0 to end the list
648  *
649  * Associate given format/value pairs with each other.
650  *
651  * Returns: a pointer to the newly added entry in the index.
652  */
653 GstIndexEntry *
654 gst_index_add_associationv (GstIndex * index, gint id, GstAssocFlags flags,
655     int n, const GstIndexAssociation * list)
656 {
657   GstIndexEntry *entry;
658
659   g_return_val_if_fail (n > 0, NULL);
660   g_return_val_if_fail (list != NULL, NULL);
661   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
662
663   if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
664     return NULL;
665
666   entry = g_malloc (sizeof (GstIndexEntry));
667
668   entry->type = GST_INDEX_ENTRY_ASSOCIATION;
669   entry->id = id;
670   entry->data.assoc.flags = flags;
671   entry->data.assoc.assocs = g_memdup (list, sizeof (GstIndexAssociation) * n);
672   entry->data.assoc.nassocs = n;
673
674   gst_index_add_entry (index, entry);
675
676   return entry;
677 }
678
679 /**
680  * gst_index_add_association:
681  * @index: the index to add the entry to
682  * @id: the id of the index writer
683  * @flags: optinal flags for this entry
684  * @format: the format of the value
685  * @value: the value
686  * @...: other format/value pairs or 0 to end the list
687  *
688  * Associate given format/value pairs with each other.
689  * Be sure to pass gint64 values to this functions varargs,
690  * you might want to use a gint64 cast to be sure.
691  *
692  * Returns: a pointer to the newly added entry in the index.
693  */
694 GstIndexEntry *
695 gst_index_add_association (GstIndex * index, gint id, GstAssocFlags flags,
696     GstFormat format, gint64 value, ...)
697 {
698   va_list args;
699   GstIndexEntry *entry;
700   GstIndexAssociation *list;
701   gint n_assocs = 0;
702   GstFormat cur_format;
703   GArray *array;
704
705   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
706   g_return_val_if_fail (format != 0, NULL);
707
708   if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
709     return NULL;
710
711   array = g_array_new (FALSE, FALSE, sizeof (GstIndexAssociation));
712
713   va_start (args, value);
714
715   cur_format = format;
716   n_assocs = 0;
717   while (cur_format) {
718     GstIndexAssociation a;
719
720     n_assocs++;
721     cur_format = va_arg (args, GstFormat);
722     if (cur_format) {
723       a.format = cur_format;
724       a.value = va_arg (args, gint64);
725
726       g_array_append_val (array, a);
727     }
728   }
729   va_end (args);
730
731   list = (GstIndexAssociation *) g_array_free (array, FALSE);
732
733   entry = gst_index_add_associationv (index, id, flags, n_assocs, list);
734   g_free (list);
735
736   return entry;
737 }
738
739 /**
740  * gst_index_add_object:
741  * @index: the index to add the object to
742  * @id: the id of the index writer
743  * @key: a key for the object
744  * @type: the GType of the object
745  * @object: a pointer to the object to add
746  *
747  * Add the given object to the index with the given key.
748  *
749  * This function is not yet implemented.
750  *
751  * Returns: a pointer to the newly added entry in the index.
752  */
753 GstIndexEntry *
754 gst_index_add_object (GstIndex * index, gint id, gchar * key,
755     GType type, gpointer object)
756 {
757   if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
758     return NULL;
759
760   return NULL;
761 }
762
763 static gint
764 gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
765 {
766   if (a < b)
767     return -1;
768   if (a > b)
769     return 1;
770   return 0;
771 }
772
773 /**
774  * gst_index_get_assoc_entry:
775  * @index: the index to search
776  * @id: the id of the index writer
777  * @method: The lookup method to use
778  * @flags: Flags for the entry
779  * @format: the format of the value
780  * @value: the value to find
781  *
782  * Finds the given format/value in the index
783  *
784  * Returns: the entry associated with the value or NULL if the
785  *   value was not found.
786  */
787 GstIndexEntry *
788 gst_index_get_assoc_entry (GstIndex * index, gint id,
789     GstIndexLookupMethod method, GstAssocFlags flags,
790     GstFormat format, gint64 value)
791 {
792   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
793
794   if (id == -1)
795     return NULL;
796
797   return gst_index_get_assoc_entry_full (index, id, method, flags, format,
798       value, gst_index_compare_func, NULL);
799 }
800
801 /**
802  * gst_index_get_assoc_entry_full:
803  * @index: the index to search
804  * @id: the id of the index writer
805  * @method: The lookup method to use
806  * @flags: Flags for the entry
807  * @format: the format of the value
808  * @value: the value to find
809  * @func: the function used to compare entries
810  * @user_data: user data passed to the compare function
811  *
812  * Finds the given format/value in the index with the given
813  * compare function and user_data.
814  *
815  * Returns: the entry associated with the value or NULL if the
816  *   value was not found.
817  */
818 GstIndexEntry *
819 gst_index_get_assoc_entry_full (GstIndex * index, gint id,
820     GstIndexLookupMethod method, GstAssocFlags flags,
821     GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
822 {
823   GstIndexClass *iclass;
824
825   g_return_val_if_fail (GST_IS_INDEX (index), NULL);
826
827   if (id == -1)
828     return NULL;
829
830   iclass = GST_INDEX_GET_CLASS (index);
831
832   if (iclass->get_assoc_entry)
833     return iclass->get_assoc_entry (index, id, method, flags, format, value,
834         func, user_data);
835
836   return NULL;
837 }
838
839 /**
840  * gst_index_entry_assoc_map:
841  * @entry: the index to search
842  * @format: the format of the value the find
843  * @value: a pointer to store the value
844  *
845  * Gets alternative formats associated with the indexentry.
846  *
847  * Returns: TRUE if there was a value associated with the given
848  * format.
849  */
850 gboolean
851 gst_index_entry_assoc_map (GstIndexEntry * entry,
852     GstFormat format, gint64 * value)
853 {
854   gint i;
855
856   g_return_val_if_fail (entry != NULL, FALSE);
857   g_return_val_if_fail (value != NULL, FALSE);
858
859   for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
860     if (GST_INDEX_ASSOC_FORMAT (entry, i) == format) {
861       *value = GST_INDEX_ASSOC_VALUE (entry, i);
862       return TRUE;
863     }
864   }
865   return FALSE;
866 }