source: trunk/third/gstreamer/gst/gstindex.c @ 21005

Revision 21005, 24.8 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21004, which included commits to RCS files with non-trunk default branches.
Line 
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#include "gst_private.h"
24
25#include "gstinfo.h"
26#include "gstregistrypool.h"
27#include "gstpad.h"
28#include "gstindex.h"
29#include "gstmarshal.h"
30
31/* Index signals and args */
32enum
33{
34  ENTRY_ADDED,
35  LAST_SIGNAL
36};
37
38enum
39{
40  ARG_0,
41  ARG_RESOLVER
42      /* FILL ME */
43};
44
45static void gst_index_class_init (GstIndexClass * klass);
46static void gst_index_init (GstIndex * index);
47
48static void gst_index_set_property (GObject * object, guint prop_id,
49    const GValue * value, GParamSpec * pspec);
50static void gst_index_get_property (GObject * object, guint prop_id,
51    GValue * value, GParamSpec * pspec);
52
53static GstIndexGroup *gst_index_group_new (guint groupnum);
54
55static gboolean gst_index_path_resolver (GstIndex * index, GstObject * writer,
56    gchar ** writer_string, gpointer data);
57static gboolean gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
58    gchar ** writer_string, gpointer data);
59static void gst_index_add_entry (GstIndex * index, GstIndexEntry * entry);
60
61static GstObject *parent_class = NULL;
62static guint gst_index_signals[LAST_SIGNAL] = { 0 };
63
64typedef struct
65{
66  GstIndexResolverMethod method;
67  GstIndexResolver resolver;
68  gpointer user_data;
69}
70ResolverEntry;
71
72static const ResolverEntry resolvers[] = {
73  {GST_INDEX_RESOLVER_CUSTOM, NULL, NULL},
74  {GST_INDEX_RESOLVER_GTYPE, gst_index_gtype_resolver, NULL},
75  {GST_INDEX_RESOLVER_PATH, gst_index_path_resolver, NULL},
76};
77
78#define GST_TYPE_INDEX_RESOLVER (gst_index_resolver_get_type())
79static GType
80gst_index_resolver_get_type (void)
81{
82  static GType index_resolver_type = 0;
83  static GEnumValue index_resolver[] = {
84    {GST_INDEX_RESOLVER_CUSTOM, "GST_INDEX_RESOLVER_CUSTOM",
85        "Use a custom resolver"},
86    {GST_INDEX_RESOLVER_GTYPE, "GST_INDEX_RESOLVER_GTYPE",
87        "Resolve an object to its GType[.padname]"},
88    {GST_INDEX_RESOLVER_PATH, "GST_INDEX_RESOLVER_PATH",
89        "Resolve an object to its path in the pipeline"},
90    {0, NULL, NULL},
91  };
92
93  if (!index_resolver_type) {
94    index_resolver_type =
95        g_enum_register_static ("GstIndexResolver", index_resolver);
96  }
97  return index_resolver_type;
98}
99
100GType
101gst_index_entry_get_type (void)
102{
103  static GType index_entry_type = 0;
104
105  if (!index_entry_type) {
106    index_entry_type = g_boxed_type_register_static ("GstIndexEntry",
107        (GBoxedCopyFunc) gst_index_entry_copy,
108        (GBoxedFreeFunc) gst_index_entry_free);
109  }
110  return index_entry_type;
111}
112
113
114GType
115gst_index_get_type (void)
116{
117  static GType index_type = 0;
118
119  if (!index_type) {
120    static const GTypeInfo index_info = {
121      sizeof (GstIndexClass),
122      NULL,
123      NULL,
124      (GClassInitFunc) gst_index_class_init,
125      NULL,
126      NULL,
127      sizeof (GstIndex),
128      0,
129      (GInstanceInitFunc) gst_index_init,
130      NULL
131    };
132
133    index_type =
134        g_type_register_static (GST_TYPE_OBJECT, "GstIndex", &index_info, 0);
135  }
136  return index_type;
137}
138
139static void
140gst_index_class_init (GstIndexClass * klass)
141{
142  GObjectClass *gobject_class;
143  GstElementClass *gstelement_class;
144
145  gobject_class = (GObjectClass *) klass;
146  gstelement_class = (GstElementClass *) klass;
147
148  parent_class = g_type_class_ref (GST_TYPE_OBJECT);
149
150  gst_index_signals[ENTRY_ADDED] =
151      g_signal_new ("entry-added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
152      G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL,
153      gst_marshal_VOID__BOXED, G_TYPE_NONE, 1, GST_TYPE_INDEX_ENTRY);
154
155  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_index_set_property);
156  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_index_get_property);
157
158  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_RESOLVER,
159      g_param_spec_enum ("resolver", "Resolver",
160          "Select a predefined object to string mapper",
161          GST_TYPE_INDEX_RESOLVER, GST_INDEX_RESOLVER_PATH, G_PARAM_READWRITE));
162}
163
164static void
165gst_index_init (GstIndex * index)
166{
167  index->curgroup = gst_index_group_new (0);
168  index->maxgroup = 0;
169  index->groups = g_list_prepend (NULL, index->curgroup);
170
171  index->writers = g_hash_table_new (NULL, NULL);
172  index->last_id = 0;
173
174  index->method = GST_INDEX_RESOLVER_PATH;
175  index->resolver = resolvers[index->method].resolver;
176  index->resolver_user_data = resolvers[index->method].user_data;
177
178  GST_FLAG_SET (index, GST_INDEX_WRITABLE);
179  GST_FLAG_SET (index, GST_INDEX_READABLE);
180
181  GST_DEBUG ("created new index");
182}
183
184static void
185gst_index_set_property (GObject * object, guint prop_id,
186    const GValue * value, GParamSpec * pspec)
187{
188  GstIndex *index;
189
190  index = GST_INDEX (object);
191
192  switch (prop_id) {
193    case ARG_RESOLVER:
194      index->method = g_value_get_enum (value);
195      index->resolver = resolvers[index->method].resolver;
196      index->resolver_user_data = resolvers[index->method].user_data;
197      break;
198    default:
199      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
200      break;
201  }
202}
203
204static void
205gst_index_get_property (GObject * object, guint prop_id,
206    GValue * value, GParamSpec * pspec)
207{
208  GstIndex *index;
209
210  index = GST_INDEX (object);
211
212  switch (prop_id) {
213    case ARG_RESOLVER:
214      g_value_set_enum (value, index->method);
215      break;
216    default:
217      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
218      break;
219  }
220}
221
222static GstIndexGroup *
223gst_index_group_new (guint groupnum)
224{
225  GstIndexGroup *indexgroup = g_new (GstIndexGroup, 1);
226
227  indexgroup->groupnum = groupnum;
228  indexgroup->entries = NULL;
229  indexgroup->certainty = GST_INDEX_UNKNOWN;
230  indexgroup->peergroup = -1;
231
232  GST_DEBUG ("created new index group %d", groupnum);
233
234  return indexgroup;
235}
236
237/**
238 * gst_index_new:
239 *
240 * Create a new tileindex object
241 *
242 * Returns: a new index object
243 */
244GstIndex *
245gst_index_new (void)
246{
247  GstIndex *index;
248
249  index = g_object_new (gst_index_get_type (), NULL);
250
251  return index;
252}
253
254/**
255 * gst_index_commit:
256 * @index: the index to commit
257 * @id: the writer that commited the index
258 *
259 * Tell the index that the writer with the given id is done
260 * with this index and is not going to write any more entries
261 * to it.
262 */
263void
264gst_index_commit (GstIndex * index, gint id)
265{
266  GstIndexClass *iclass;
267
268  iclass = GST_INDEX_GET_CLASS (index);
269
270  if (iclass->commit)
271    iclass->commit (index, id);
272}
273
274
275/**
276 * gst_index_get_group:
277 * @index: the index to get the current group from
278 *
279 * Get the id of the current group.
280 *
281 * Returns: the id of the current group.
282 */
283gint
284gst_index_get_group (GstIndex * index)
285{
286  return index->curgroup->groupnum;
287}
288
289/**
290 * gst_index_new_group:
291 * @index: the index to create the new group in
292 *
293 * Create a new group for the given index. It will be
294 * set as the current group.
295 *
296 * Returns: the id of the newly created group.
297 */
298gint
299gst_index_new_group (GstIndex * index)
300{
301  index->curgroup = gst_index_group_new (++index->maxgroup);
302  index->groups = g_list_append (index->groups, index->curgroup);
303  GST_DEBUG ("created new group %d in index", index->maxgroup);
304  return index->maxgroup;
305}
306
307/**
308 * gst_index_set_group:
309 * @index: the index to set the new group in
310 * @groupnum: the groupnumber to set
311 *
312 * Set the current groupnumber to the given argument.
313 *
314 * Returns: TRUE if the operation succeeded, FALSE if the group
315 * did not exist.
316 */
317gboolean
318gst_index_set_group (GstIndex * index, gint groupnum)
319{
320  GList *list;
321  GstIndexGroup *indexgroup;
322
323  /* first check for null change */
324  if (groupnum == index->curgroup->groupnum)
325    return TRUE;
326
327  /* else search for the proper group */
328  list = index->groups;
329  while (list) {
330    indexgroup = (GstIndexGroup *) (list->data);
331    list = g_list_next (list);
332    if (indexgroup->groupnum == groupnum) {
333      index->curgroup = indexgroup;
334      GST_DEBUG ("switched to index group %d", indexgroup->groupnum);
335      return TRUE;
336    }
337  }
338
339  /* couldn't find the group in question */
340  GST_DEBUG ("couldn't find index group %d", groupnum);
341  return FALSE;
342}
343
344/**
345 * gst_index_set_certainty:
346 * @index: the index to set the certainty on
347 * @certainty: the certainty to set
348 *
349 * Set the certainty of the given index.
350 */
351void
352gst_index_set_certainty (GstIndex * index, GstIndexCertainty certainty)
353{
354  index->curgroup->certainty = certainty;
355}
356
357/**
358 * gst_index_get_certainty:
359 * @index: the index to get the certainty of
360 *
361 * Get the certainty of the given index.
362 *
363 * Returns: the certainty of the index.
364 */
365GstIndexCertainty
366gst_index_get_certainty (GstIndex * index)
367{
368  return index->curgroup->certainty;
369}
370
371/**
372 * gst_index_set_filter:
373 * @index: the index to register the filter on
374 * @filter: the filter to register
375 * @user_data: data passed to the filter function
376 *
377 * Lets the app register a custom filter function so that
378 * it can select what entries should be stored in the index.
379 */
380void
381gst_index_set_filter (GstIndex * index,
382    GstIndexFilter filter, gpointer user_data)
383{
384  g_return_if_fail (GST_IS_INDEX (index));
385
386  index->filter = filter;
387  index->filter_user_data = user_data;
388}
389
390/**
391 * gst_index_set_resolver:
392 * @index: the index to register the resolver on
393 * @resolver: the resolver to register
394 * @user_data: data passed to the resolver function
395 *
396 * Lets the app register a custom function to map index
397 * ids to writer descriptions.
398 */
399void
400gst_index_set_resolver (GstIndex * index,
401    GstIndexResolver resolver, gpointer user_data)
402{
403  g_return_if_fail (GST_IS_INDEX (index));
404
405  index->resolver = resolver;
406  index->resolver_user_data = user_data;
407  index->method = GST_INDEX_RESOLVER_CUSTOM;
408}
409
410/**
411 * gst_index_entry_copy:
412 * @entry: the entry to copy
413 *
414 * Copies an entry and returns the result.
415 *
416 * Returns: a newly allocated #GstIndexEntry.
417 */
418GstIndexEntry *
419gst_index_entry_copy (GstIndexEntry * entry)
420{
421  return g_memdup (entry, sizeof (*entry));
422}
423
424/**
425 * gst_index_entry_free:
426 * @entry: the entry to free
427 *
428 * Free the memory used by the given entry.
429 */
430void
431gst_index_entry_free (GstIndexEntry * entry)
432{
433  g_free (entry);
434}
435
436/**
437 * gst_index_add_format:
438 * @index: the index to add the entry to
439 * @id: the id of the index writer
440 * @format: the format to add to the index
441 *
442 * Adds a format entry into the index. This function is
443 * used to map dynamic GstFormat ids to their original
444 * format key.
445 *
446 * Returns: a pointer to the newly added entry in the index.
447 */
448GstIndexEntry *
449gst_index_add_format (GstIndex * index, gint id, GstFormat format)
450{
451  GstIndexEntry *entry;
452  const GstFormatDefinition *def;
453
454  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
455  g_return_val_if_fail (format != 0, NULL);
456
457  if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
458    return NULL;
459
460  entry = g_new0 (GstIndexEntry, 1);
461  entry->type = GST_INDEX_ENTRY_FORMAT;
462  entry->id = id;
463  entry->data.format.format = format;
464
465  def = gst_format_get_details (format);
466  entry->data.format.key = def->nick;
467
468  gst_index_add_entry (index, entry);
469
470  return entry;
471}
472
473/**
474 * gst_index_add_id:
475 * @index: the index to add the entry to
476 * @id: the id of the index writer
477 * @description: the description of the index writer
478 *
479 * Add an id entry into the index.
480 *
481 * Returns: a pointer to the newly added entry in the index.
482 */
483GstIndexEntry *
484gst_index_add_id (GstIndex * index, gint id, gchar * description)
485{
486  GstIndexEntry *entry;
487
488  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
489  g_return_val_if_fail (description != NULL, NULL);
490
491  if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
492    return NULL;
493
494  entry = g_new0 (GstIndexEntry, 1);
495  entry->type = GST_INDEX_ENTRY_ID;
496  entry->id = id;
497  entry->data.id.description = description;
498
499  gst_index_add_entry (index, entry);
500
501  return entry;
502}
503
504static gboolean
505gst_index_path_resolver (GstIndex * index, GstObject * writer,
506    gchar ** writer_string, gpointer data)
507{
508  *writer_string = gst_object_get_path_string (writer);
509
510  return TRUE;
511}
512
513static gboolean
514gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
515    gchar ** writer_string, gpointer data)
516{
517  if (GST_IS_PAD (writer)) {
518    GstElement *element = gst_pad_get_parent (GST_PAD (writer));
519
520    *writer_string = g_strdup_printf ("%s.%s",
521        g_type_name (G_OBJECT_TYPE (element)), gst_object_get_name (writer));
522  } else {
523    *writer_string =
524        g_strdup_printf ("%s", g_type_name (G_OBJECT_TYPE (writer)));
525  }
526
527  return TRUE;
528}
529
530/**
531 * gst_index_get_writer_id:
532 * @index: the index to get a unique write id for
533 * @writer: the GstObject to allocate an id for
534 * @id: a pointer to a gint to hold the id
535 *
536 * Before entries can be added to the index, a writer
537 * should obtain a unique id. The methods to add new entries
538 * to the index require this id as an argument.
539 *
540 * The application can implement a custom function to map the writer object
541 * to a string. That string will be used to register or look up an id
542 * in the index.
543 *
544 * Returns: TRUE if the writer would be mapped to an id.
545 */
546gboolean
547gst_index_get_writer_id (GstIndex * index, GstObject * writer, gint * id)
548{
549  gchar *writer_string = NULL;
550  GstIndexEntry *entry;
551  GstIndexClass *iclass;
552  gboolean success = FALSE;
553
554  g_return_val_if_fail (GST_IS_INDEX (index), FALSE);
555  g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE);
556  g_return_val_if_fail (id, FALSE);
557
558  *id = -1;
559
560  /* first try to get a previously cached id */
561  entry = g_hash_table_lookup (index->writers, writer);
562  if (entry == NULL) {
563
564    iclass = GST_INDEX_GET_CLASS (index);
565
566    /* let the app make a string */
567    if (index->resolver) {
568      gboolean res;
569
570      res =
571          index->resolver (index, writer, &writer_string,
572          index->resolver_user_data);
573      if (!res)
574        return FALSE;
575    } else {
576      g_warning ("no resolver found");
577      return FALSE;
578    }
579
580    /* if the index has a resolver, make it map this string to an id */
581    if (iclass->get_writer_id) {
582      success = iclass->get_writer_id (index, id, writer_string);
583    }
584    /* if the index could not resolve, we allocate one ourselves */
585    if (!success) {
586      *id = ++index->last_id;
587    }
588
589    entry = gst_index_add_id (index, *id, writer_string);
590    if (!entry) {
591      /* index is probably not writable, make an entry anyway
592       * to keep it in our cache */
593      entry = g_new0 (GstIndexEntry, 1);
594      entry->type = GST_INDEX_ENTRY_ID;
595      entry->id = *id;
596      entry->data.id.description = writer_string;
597    }
598    g_hash_table_insert (index->writers, writer, entry);
599  } else {
600    *id = entry->id;
601  }
602
603  return TRUE;
604}
605
606static void
607gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
608{
609  GstIndexClass *iclass;
610
611  iclass = GST_INDEX_GET_CLASS (index);
612
613  if (iclass->add_entry) {
614    iclass->add_entry (index, entry);
615  }
616
617  g_signal_emit (G_OBJECT (index), gst_index_signals[ENTRY_ADDED], 0, entry);
618}
619
620/**
621 * gst_index_add_associationv:
622 * @index: the index to add the entry to
623 * @id: the id of the index writer
624 * @flags: optinal flags for this entry
625 * @n: number of associations
626 * @list: list of associations
627 * @...: other format/value pairs or 0 to end the list
628 *
629 * Associate given format/value pairs with each other.
630 *
631 * Returns: a pointer to the newly added entry in the index.
632 */
633GstIndexEntry *
634gst_index_add_associationv (GstIndex * index, gint id, GstAssocFlags flags,
635    int n, const GstIndexAssociation * list)
636{
637  GstIndexEntry *entry;
638
639  g_return_val_if_fail (n > 0, NULL);
640  g_return_val_if_fail (list != NULL, NULL);
641  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
642
643  if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
644    return NULL;
645
646  entry = g_malloc (sizeof (GstIndexEntry));
647
648  entry->type = GST_INDEX_ENTRY_ASSOCIATION;
649  entry->id = id;
650  entry->data.assoc.flags = flags;
651  entry->data.assoc.assocs = g_memdup (list, sizeof (GstIndexAssociation) * n);
652  entry->data.assoc.nassocs = n;
653
654  gst_index_add_entry (index, entry);
655
656  return entry;
657}
658
659/**
660 * gst_index_add_association:
661 * @index: the index to add the entry to
662 * @id: the id of the index writer
663 * @flags: optinal flags for this entry
664 * @format: the format of the value
665 * @value: the value
666 * @...: other format/value pairs or 0 to end the list
667 *
668 * Associate given format/value pairs with each other.
669 * Be sure to pass gint64 values to this functions varargs,
670 * you might want to use a gint64 cast to be sure.
671 *
672 * Returns: a pointer to the newly added entry in the index.
673 */
674GstIndexEntry *
675gst_index_add_association (GstIndex * index, gint id, GstAssocFlags flags,
676    GstFormat format, gint64 value, ...)
677{
678  va_list args;
679  GstIndexEntry *entry;
680  GstIndexAssociation *list;
681  gint n_assocs = 0;
682  GstFormat cur_format;
683  GArray *array;
684
685  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
686  g_return_val_if_fail (format != 0, NULL);
687
688  if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
689    return NULL;
690
691  array = g_array_new (FALSE, FALSE, sizeof (GstIndexAssociation));
692
693  va_start (args, value);
694
695  cur_format = format;
696  n_assocs = 0;
697  while (cur_format) {
698    GstIndexAssociation a;
699
700    n_assocs++;
701    cur_format = va_arg (args, GstFormat);
702    if (cur_format) {
703      a.format = cur_format;
704      a.value = va_arg (args, gint64);
705
706      g_array_append_val (array, a);
707    }
708  }
709  va_end (args);
710
711  list = (GstIndexAssociation *) g_array_free (array, FALSE);
712
713  entry = gst_index_add_associationv (index, id, flags, n_assocs, list);
714  g_free (list);
715
716  return entry;
717}
718
719/**
720 * gst_index_add_object:
721 * @index: the index to add the object to
722 * @id: the id of the index writer
723 * @key: a key for the object
724 * @type: the GType of the object
725 * @object: a pointer to the object to add
726 *
727 * Add the given object to the index with the given key.
728 *
729 * Returns: a pointer to the newly added entry in the index.
730 */
731GstIndexEntry *
732gst_index_add_object (GstIndex * index, gint id, gchar * key,
733    GType type, gpointer object)
734{
735  if (!GST_INDEX_IS_WRITABLE (index) || id == -1)
736    return NULL;
737
738  return NULL;
739}
740
741static gint
742gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
743{
744  if (a < b)
745    return -1;
746  if (a > b)
747    return 1;
748  return 0;
749}
750
751/**
752 * gst_index_get_assoc_entry:
753 * @index: the index to search
754 * @id: the id of the index writer
755 * @method: The lookup method to use
756 * @flags: Flags for the entry
757 * @format: the format of the value
758 * @value: the value to find
759 *
760 * Finds the given format/value in the index
761 *
762 * Returns: the entry associated with the value or NULL if the
763 *   value was not found.
764 */
765GstIndexEntry *
766gst_index_get_assoc_entry (GstIndex * index, gint id,
767    GstIndexLookupMethod method, GstAssocFlags flags,
768    GstFormat format, gint64 value)
769{
770  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
771
772  if (id == -1)
773    return NULL;
774
775  return gst_index_get_assoc_entry_full (index, id, method, flags, format,
776      value, gst_index_compare_func, NULL);
777}
778
779/**
780 * gst_index_get_assoc_entry_full:
781 * @index: the index to search
782 * @id: the id of the index writer
783 * @method: The lookup method to use
784 * @flags: Flags for the entry
785 * @format: the format of the value
786 * @value: the value to find
787 * @func: the function used to compare entries
788 * @user_data: user data passed to the compare function
789 *
790 * Finds the given format/value in the index with the given
791 * compare function and user_data.
792 *
793 * Returns: the entry associated with the value or NULL if the
794 *   value was not found.
795 */
796GstIndexEntry *
797gst_index_get_assoc_entry_full (GstIndex * index, gint id,
798    GstIndexLookupMethod method, GstAssocFlags flags,
799    GstFormat format, gint64 value, GCompareDataFunc func, gpointer user_data)
800{
801  GstIndexClass *iclass;
802
803  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
804
805  if (id == -1)
806    return NULL;
807
808  iclass = GST_INDEX_GET_CLASS (index);
809
810  if (iclass->get_assoc_entry)
811    return iclass->get_assoc_entry (index, id, method, flags, format, value,
812        func, user_data);
813
814  return NULL;
815}
816
817/**
818 * gst_index_entry_assoc_map:
819 * @entry: the index to search
820 * @format: the format of the value the find
821 * @value: a pointer to store the value
822 *
823 * Gets alternative formats associated with the indexentry.
824 *
825 * Returns: TRUE if there was a value associated with the given
826 * format.
827 */
828gboolean
829gst_index_entry_assoc_map (GstIndexEntry * entry,
830    GstFormat format, gint64 * value)
831{
832  gint i;
833
834  g_return_val_if_fail (entry != NULL, FALSE);
835  g_return_val_if_fail (value != NULL, FALSE);
836
837  for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
838    if (GST_INDEX_ASSOC_FORMAT (entry, i) == format) {
839      *value = GST_INDEX_ASSOC_VALUE (entry, i);
840      return TRUE;
841    }
842  }
843  return FALSE;
844}
845
846
847static void gst_index_factory_class_init (GstIndexFactoryClass * klass);
848static void gst_index_factory_init (GstIndexFactory * factory);
849
850static GstPluginFeatureClass *factory_parent_class = NULL;
851
852/* static guint gst_index_factory_signals[LAST_SIGNAL] = { 0 }; */
853
854GType
855gst_index_factory_get_type (void)
856{
857  static GType indexfactory_type = 0;
858
859  if (!indexfactory_type) {
860    static const GTypeInfo indexfactory_info = {
861      sizeof (GstIndexFactoryClass),
862      NULL,
863      NULL,
864      (GClassInitFunc) gst_index_factory_class_init,
865      NULL,
866      NULL,
867      sizeof (GstIndexFactory),
868      0,
869      (GInstanceInitFunc) gst_index_factory_init,
870      NULL
871    };
872
873    indexfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE,
874        "GstIndexFactory", &indexfactory_info, 0);
875  }
876  return indexfactory_type;
877}
878
879static void
880gst_index_factory_class_init (GstIndexFactoryClass * klass)
881{
882  GObjectClass *gobject_class;
883  GstObjectClass *gstobject_class;
884  GstPluginFeatureClass *gstpluginfeature_class;
885
886  gobject_class = (GObjectClass *) klass;
887  gstobject_class = (GstObjectClass *) klass;
888  gstpluginfeature_class = (GstPluginFeatureClass *) klass;
889
890  factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
891}
892
893static void
894gst_index_factory_init (GstIndexFactory * factory)
895{
896}
897
898/**
899 * gst_index_factory_new:
900 * @name: name of indexfactory to create
901 * @longdesc: long description of indexfactory to create
902 * @type: the GType of the GstIndex element of this factory
903 *
904 * Create a new indexfactory with the given parameters
905 *
906 * Returns: a new #GstIndexFactory.
907 */
908GstIndexFactory *
909gst_index_factory_new (const gchar * name, const gchar * longdesc, GType type)
910{
911  GstIndexFactory *factory;
912
913  g_return_val_if_fail (name != NULL, NULL);
914  factory = gst_index_factory_find (name);
915  if (!factory) {
916    factory = GST_INDEX_FACTORY (g_object_new (GST_TYPE_INDEX_FACTORY, NULL));
917  }
918
919  GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
920  if (factory->longdesc)
921    g_free (factory->longdesc);
922  factory->longdesc = g_strdup (longdesc);
923  factory->type = type;
924
925  return factory;
926}
927
928/**
929 * gst_index_factory_destroy:
930 * @factory: factory to destroy
931 *
932 * Removes the index from the global list.
933 */
934void
935gst_index_factory_destroy (GstIndexFactory * factory)
936{
937  g_return_if_fail (factory != NULL);
938
939  /* we don't free the struct bacause someone might  have a handle to it.. */
940}
941
942/**
943 * gst_index_factory_find:
944 * @name: name of indexfactory to find
945 *
946 * Search for an indexfactory of the given name.
947 *
948 * Returns: #GstIndexFactory if found, NULL otherwise
949 */
950GstIndexFactory *
951gst_index_factory_find (const gchar * name)
952{
953  GstPluginFeature *feature;
954
955  g_return_val_if_fail (name != NULL, NULL);
956
957  GST_DEBUG ("gstindex: find \"%s\"", name);
958
959  feature = gst_registry_pool_find_feature (name, GST_TYPE_INDEX_FACTORY);
960  if (feature)
961    return GST_INDEX_FACTORY (feature);
962
963  return NULL;
964}
965
966/**
967 * gst_index_factory_create:
968 * @factory: the factory used to create the instance
969 *
970 * Create a new #GstIndex instance from the
971 * given indexfactory.
972 *
973 * Returns: A new #GstIndex instance.
974 */
975GstIndex *
976gst_index_factory_create (GstIndexFactory * factory)
977{
978  GstIndex *new = NULL;
979
980  g_return_val_if_fail (factory != NULL, NULL);
981
982  if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
983    g_return_val_if_fail (factory->type != 0, NULL);
984
985    new = GST_INDEX (g_object_new (factory->type, NULL));
986  }
987
988  return new;
989}
990
991/**
992 * gst_index_factory_make:
993 * @name: the name of the factory used to create the instance
994 *
995 * Create a new #GstIndex instance from the
996 * indexfactory with the given name.
997 *
998 * Returns: A new #GstIndex instance.
999 */
1000GstIndex *
1001gst_index_factory_make (const gchar * name)
1002{
1003  GstIndexFactory *factory;
1004
1005  g_return_val_if_fail (name != NULL, NULL);
1006
1007  factory = gst_index_factory_find (name);
1008
1009  if (factory == NULL)
1010    return NULL;
1011
1012  return gst_index_factory_create (factory);
1013}
Note: See TracBrowser for help on using the repository browser.