cache->index
authorWim Taymans <wim.taymans@gmail.com>
Thu, 12 Dec 2002 22:16:11 +0000 (22:16 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 12 Dec 2002 22:16:11 +0000 (22:16 +0000)
Original commit message from CVS:
cache->index

gst/gstindex.c [new file with mode: 0644]
gst/gstindex.h [new file with mode: 0644]

diff --git a/gst/gstindex.c b/gst/gstindex.c
new file mode 100644 (file)
index 0000000..df62e8b
--- /dev/null
@@ -0,0 +1,662 @@
+/* GStreamer
+ * Copyright (C) 2001 RidgeRun (http://www.ridgerun.com/)
+ * Written by Erik Walthinsen <omega@ridgerun.com>
+ *
+ * gstindex.c: Index for mappings and other data
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstlog.h"
+#include "gst_private.h"
+#include "gstregistry.h"
+
+#include "gstindex.h"
+
+/* Index signals and args */
+enum {
+  ENTRY_ADDED,
+  LAST_SIGNAL
+};
+
+enum {
+  ARG_0,
+  /* FILL ME */
+};
+
+static void            gst_index_class_init    (GstIndexClass *klass);
+static void            gst_index_init          (GstIndex *index);
+
+#define CLASS(index)  GST_INDEX_CLASS (G_OBJECT_GET_CLASS (index))
+
+static GstObject *parent_class = NULL;
+static guint gst_index_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_index_get_type(void) {
+  static GType index_type = 0;
+
+  if (!index_type) {
+    static const GTypeInfo index_info = {
+      sizeof(GstIndexClass),
+      NULL,
+      NULL,
+      (GClassInitFunc)gst_index_class_init,
+      NULL,
+      NULL,
+      sizeof(GstIndex),
+      1,
+      (GInstanceInitFunc)gst_index_init,
+      NULL
+    };
+    index_type = g_type_register_static(GST_TYPE_OBJECT, "GstIndex", &index_info, 0);
+  }
+  return index_type;
+}
+
+static void
+gst_index_class_init (GstIndexClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstelement_class = (GstElementClass*)klass;
+
+  parent_class = g_type_class_ref(GST_TYPE_OBJECT);
+
+  gst_index_signals[ENTRY_ADDED] =
+    g_signal_new ("entry_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GstIndexClass, entry_added), NULL, NULL,
+                  gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
+                  G_TYPE_POINTER);
+}
+
+static GstIndexGroup *
+gst_index_group_new(guint groupnum)
+{
+  GstIndexGroup *indexgroup = g_new(GstIndexGroup,1);
+
+  indexgroup->groupnum = groupnum;
+  indexgroup->entries = NULL;
+  indexgroup->certainty = GST_INDEX_UNKNOWN;
+  indexgroup->peergroup = -1;
+
+  GST_DEBUG(0, "created new index group %d",groupnum);
+
+  return indexgroup;
+}
+
+static void
+gst_index_init (GstIndex *index)
+{
+  index->curgroup = gst_index_group_new(0);
+  index->maxgroup = 0;
+  index->groups = g_list_prepend(NULL, index->curgroup);
+
+  index->writers = g_hash_table_new (NULL, NULL);
+  index->last_id = 0;
+  
+  GST_DEBUG(0, "created new index");
+}
+
+/**
+ * gst_index_new:
+ *
+ * Create a new tileindex object
+ *
+ * Returns: a new index object
+ */
+GstIndex *
+gst_index_new()
+{
+  GstIndex *index;
+
+  index = g_object_new (gst_index_get_type (), NULL);
+
+  return index;
+}
+
+/**
+ * gst_index_get_group:
+ * @index: the index to get the current group from
+ *
+ * Get the id of the current group.
+ *
+ * Returns: the id of the current group.
+ */
+gint
+gst_index_get_group(GstIndex *index)
+{
+  return index->curgroup->groupnum;
+}
+
+/**
+ * gst_index_new_group:
+ * @index: the index to create the new group in
+ *
+ * Create a new group for the given index. It will be
+ * set as the current group.
+ *
+ * Returns: the id of the newly created group.
+ */
+gint
+gst_index_new_group(GstIndex *index)
+{
+  index->curgroup = gst_index_group_new(++index->maxgroup);
+  index->groups = g_list_append(index->groups,index->curgroup);
+  GST_DEBUG(0, "created new group %d in index",index->maxgroup);
+  return index->maxgroup;
+}
+
+/**
+ * gst_index_set_group:
+ * @index: the index to set the new group in
+ * @groupnum: the groupnumber to set
+ *
+ * Set the current groupnumber to the given argument.
+ *
+ * Returns: TRUE if the operation succeeded, FALSE if the group
+ * did not exist.
+ */
+gboolean
+gst_index_set_group(GstIndex *index, gint groupnum)
+{
+  GList *list;
+  GstIndexGroup *indexgroup;
+
+  /* first check for null change */
+  if (groupnum == index->curgroup->groupnum)
+    return TRUE;
+
+  /* else search for the proper group */
+  list = index->groups;
+  while (list) {
+    indexgroup = (GstIndexGroup *)(list->data);
+    list = g_list_next(list);
+    if (indexgroup->groupnum == groupnum) {
+      index->curgroup = indexgroup;
+      GST_DEBUG(0, "switched to index group %d", indexgroup->groupnum);
+      return TRUE;
+    }
+  }
+
+  /* couldn't find the group in question */
+  GST_DEBUG(0, "couldn't find index group %d",groupnum);
+  return FALSE;
+}
+
+/**
+ * gst_index_set_certainty:
+ * @index: the index to set the certainty on
+ * @certainty: the certainty to set
+ *
+ * Set the certainty of the given index.
+ */
+void
+gst_index_set_certainty(GstIndex *index, GstIndexCertainty certainty)
+{
+  index->curgroup->certainty = certainty;
+}
+
+/**
+ * gst_index_get_certainty:
+ * @index: the index to get the certainty of
+ *
+ * Get the certainty of the given index.
+ *
+ * Returns: the certainty of the index.
+ */
+GstIndexCertainty
+gst_index_get_certainty(GstIndex *index)
+{
+  return index->curgroup->certainty;
+}
+
+void
+gst_index_set_filter (GstIndex *index, 
+                     GstIndexFilter filter, gpointer user_data)
+{
+  g_return_if_fail (GST_IS_INDEX (index));
+
+  index->filter = filter;
+  index->filter_user_data = user_data;
+}
+
+void
+gst_index_set_resolver (GstIndex *index, 
+                       GstIndexResolver resolver, gpointer user_data)
+{
+  g_return_if_fail (GST_IS_INDEX (index));
+
+  index->resolver = resolver;
+  index->resolver_user_data = user_data;
+}
+
+void
+gst_index_entry_free (GstIndexEntry *entry)
+{
+  g_free (entry);
+}
+
+/**
+ * gst_index_add_format:
+ * @index: the index to add the entry to
+ * @id: the id of the index writer
+ * @format: the format to add to the index
+ *
+ * Adds a format entry into the index. This function is
+ * used to map dynamic GstFormat ids to their original
+ * format key.
+ *
+ * Returns: a pointer to the newly added entry in the index.
+ */
+GstIndexEntry*
+gst_index_add_format (GstIndex *index, gint id, GstFormat format)
+{
+  GstIndexEntry *entry;
+  const GstFormatDefinition* def;
+
+  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
+  g_return_val_if_fail (format != 0, NULL);
+  
+  entry = g_new0 (GstIndexEntry, 1);
+  entry->type = GST_INDEX_ENTRY_FORMAT;
+  entry->id = id;
+  entry->data.format.format = format;
+  def = gst_format_get_details (format);
+  entry->data.format.key = def->nick;
+  
+  if (CLASS (index)->add_entry)
+    CLASS (index)->add_entry (index, entry);
+
+  g_signal_emit (G_OBJECT (index), gst_index_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
+
+/**
+ * gst_index_add_id:
+ * @index: the index to add the entry to
+ * @id: the id of the index writer
+ * @description: the description of the index writer
+ *
+ * Returns: a pointer to the newly added entry in the index.
+ */
+GstIndexEntry*
+gst_index_add_id (GstIndex *index, gint id, gchar *description)
+{
+  GstIndexEntry *entry;
+
+  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
+  g_return_val_if_fail (description != NULL, NULL);
+  
+  entry = g_new0 (GstIndexEntry, 1);
+  entry->type = GST_INDEX_ENTRY_ID;
+  entry->id = id;
+  entry->data.id.description = description;
+
+  if (CLASS (index)->add_entry)
+    CLASS (index)->add_entry (index, entry);
+  
+  g_signal_emit (G_OBJECT (index), gst_index_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
+
+/**
+ * gst_index_get_writer_id:
+ * @index: the index to get a unique write id for
+ * @writer: the GstObject to allocate an id for
+ * @id: a pointer to a gint to hold the id
+ *
+ * Before entries can be added to the index, a writer
+ * should obtain a unique id. The methods to add new entries
+ * to the index require this id as an argument. 
+ *
+ * The application or a GstIndex subclass can implement
+ * custom functions to map the writer object to an id.
+ *
+ * Returns: TRUE if the writer would be mapped to an id.
+ */
+gboolean 
+gst_index_get_writer_id (GstIndex *index, GstObject *writer, gint *id)
+{
+  gchar *writer_string = NULL;
+  gboolean success = FALSE;
+  GstIndexEntry *entry;
+
+  g_return_val_if_fail (GST_IS_INDEX (index), FALSE);
+  g_return_val_if_fail (GST_IS_OBJECT (writer), FALSE);
+  g_return_val_if_fail (id, FALSE);
+
+  *id = -1;
+
+  entry = g_hash_table_lookup (index->writers, writer);
+  if (entry == NULL) { 
+    *id = index->last_id;
+
+    writer_string = gst_object_get_path_string (writer);
+    
+    gst_index_add_id (index, *id, writer_string);
+    index->last_id++;
+    g_hash_table_insert (index->writers, writer, entry);
+  }
+
+  if (CLASS (index)->resolve_writer) {
+    success = CLASS (index)->resolve_writer (index, writer, id, &writer_string);
+  }
+
+  if (index->resolver) {
+    success = index->resolver (index, writer, id, &writer_string, index->resolver_user_data);
+  }
+
+  return success;
+}
+
+/**
+ * gst_index_add_association:
+ * @index: the index to add the entry to
+ * @id: the id of the index writer
+ * @format: the format of the value
+ * @value: the value 
+ * @...: other format/value pairs or 0 to end the list
+ *
+ * Associate given format/value pairs with eachother.
+ * Be sure to pass gint64 values to this functions varargs,
+ * you might want to use a gint64 cast to be sure.
+ *
+ * Returns: a pointer to the newly added entry in the index.
+ */
+GstIndexEntry*
+gst_index_add_association (GstIndex *index, gint id, GstAssocFlags flags, 
+                          GstFormat format, gint64 value, ...)
+{
+  va_list args;
+  GstIndexAssociation *assoc;
+  GstIndexEntry *entry;
+  gulong size;
+  gint nassocs = 0;
+  GstFormat cur_format;
+  volatile gint64 dummy;
+
+  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
+  g_return_val_if_fail (format != 0, NULL);
+  
+  va_start (args, value);
+
+  cur_format = format;
+
+  while (cur_format) {
+    nassocs++;
+    cur_format = va_arg (args, GstFormat);
+    if (cur_format)
+      dummy = va_arg (args, gint64);
+  }
+  va_end (args);
+
+  /* make room for two assoc */
+  size = sizeof (GstIndexEntry) + (sizeof (GstIndexAssociation) * nassocs);
+
+  entry = g_malloc (size);
+
+  entry->type = GST_INDEX_ENTRY_ASSOCIATION;
+  entry->id = id;
+  entry->data.assoc.flags = flags;
+  assoc = (GstIndexAssociation *) (((guint8 *) entry) + sizeof (GstIndexEntry));
+  entry->data.assoc.assocs = assoc;
+  entry->data.assoc.nassocs = nassocs;
+
+  va_start (args, value);
+  while (format) {
+    assoc->format = format;
+    assoc->value = value;
+
+    assoc++;
+
+    format = va_arg (args, GstFormat);
+    if (format)
+      value = va_arg (args, gint64);
+  }
+  va_end (args);
+
+  if (CLASS (index)->add_entry)
+    CLASS (index)->add_entry (index, entry);
+
+  g_signal_emit (G_OBJECT (index), gst_index_signals[ENTRY_ADDED], 0, entry);
+
+  return entry;
+}
+
+static gint
+gst_index_compare_func (gconstpointer a,
+                        gconstpointer b,
+                        gpointer user_data)
+{
+  return a - b;  
+}
+
+GstIndexEntry*
+gst_index_get_assoc_entry (GstIndex *index, gint id,
+                          GstIndexLookupMethod method,
+                          GstFormat format, gint64 value)
+{
+  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
+
+  return gst_index_get_assoc_entry_full (index, id, method, format, value, 
+                                 gst_index_compare_func, NULL);
+}
+
+GstIndexEntry*
+gst_index_get_assoc_entry_full (GstIndex *index, gint id,
+                               GstIndexLookupMethod method,
+                               GstFormat format, gint64 value,
+                               GCompareDataFunc func,
+                               gpointer user_data)
+{
+  g_return_val_if_fail (GST_IS_INDEX (index), NULL);
+
+  if (CLASS(index)->get_assoc_entry)
+    return CLASS (index)->get_assoc_entry (index, id, method, format, value, func, user_data);
+  
+  return NULL;
+}
+
+gboolean
+gst_index_entry_assoc_map (GstIndexEntry *entry,
+                          GstFormat format, gint64 *value)
+{
+  gint i;
+
+  g_return_val_if_fail (entry != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
+     if (GST_INDEX_ASSOC_FORMAT (entry, i) == format) {
+       *value = GST_INDEX_ASSOC_VALUE (entry, i);
+       return TRUE;
+     }
+  }
+  return FALSE;
+}
+
+
+static void            gst_index_factory_class_init            (GstIndexFactoryClass *klass);
+static void            gst_index_factory_init          (GstIndexFactory *factory);
+
+static GstPluginFeatureClass *factory_parent_class = NULL;
+/* static guint gst_index_factory_signals[LAST_SIGNAL] = { 0 }; */
+
+GType 
+gst_index_factory_get_type (void) 
+{
+  static GType indexfactory_type = 0;
+
+  if (!indexfactory_type) {
+    static const GTypeInfo indexfactory_info = {
+      sizeof (GstIndexFactoryClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_index_factory_class_init,
+      NULL,
+      NULL,
+      sizeof(GstIndexFactory),
+      0,
+      (GInstanceInitFunc) gst_index_factory_init,
+      NULL
+    };
+    indexfactory_type = g_type_register_static (GST_TYPE_PLUGIN_FEATURE, 
+                                         "GstIndexFactory", &indexfactory_info, 0);
+  }
+  return indexfactory_type;
+}
+
+static void
+gst_index_factory_class_init (GstIndexFactoryClass *klass)
+{
+  GObjectClass *gobject_class;
+  GstObjectClass *gstobject_class;
+  GstPluginFeatureClass *gstpluginfeature_class;
+
+  gobject_class = (GObjectClass*)klass;
+  gstobject_class = (GstObjectClass*)klass;
+  gstpluginfeature_class = (GstPluginFeatureClass*) klass;
+
+  factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
+}
+
+static void
+gst_index_factory_init (GstIndexFactory *factory)
+{
+}
+
+/**
+ * gst_index_factory_new:
+ * @name: name of indexfactory to create
+ * @longdesc: long description of indexfactory to create
+ * @type: the GType of the GstIndex element of this factory
+ *
+ * Create a new indexfactory with the given parameters
+ *
+ * Returns: a new #GstIndexFactory.
+ */
+GstIndexFactory*
+gst_index_factory_new (const gchar *name, const gchar *longdesc, GType type)
+{
+  GstIndexFactory *factory;
+
+  g_return_val_if_fail(name != NULL, NULL);
+  factory = gst_index_factory_find (name);
+  if (!factory) {
+    factory = GST_INDEX_FACTORY (g_object_new (GST_TYPE_INDEX_FACTORY, NULL));
+  }
+
+  GST_PLUGIN_FEATURE_NAME (factory) = g_strdup (name);
+  if (factory->longdesc)
+    g_free (factory->longdesc);
+  factory->longdesc = g_strdup (longdesc);
+  factory->type = type;
+
+  return factory;
+}
+
+/**
+ * gst_index_factory_destroy:
+ * @factory: factory to destroy
+ *
+ * Removes the index from the global list.
+ */
+void
+gst_index_factory_destroy (GstIndexFactory *factory)
+{
+  g_return_if_fail (factory != NULL);
+
+  /* we don't free the struct bacause someone might  have a handle to it.. */
+}
+
+/**
+ * gst_index_factory_find:
+ * @name: name of indexfactory to find
+ *
+ * Search for an indexfactory of the given name.
+ *
+ * Returns: #GstIndexFactory if found, NULL otherwise
+ */
+GstIndexFactory*
+gst_index_factory_find (const gchar *name)
+{
+  GstPluginFeature *feature;
+
+  g_return_val_if_fail (name != NULL, NULL);
+
+  GST_DEBUG (0,"gstindex: find \"%s\"", name);
+
+  feature = gst_registry_pool_find_feature (name, GST_TYPE_INDEX_FACTORY);
+  if (feature)
+    return GST_INDEX_FACTORY (feature);
+
+  return NULL;
+}
+
+/**
+ * gst_index_factory_create:
+ * @factory: the factory used to create the instance
+ *
+ * Create a new #GstIndex instance from the 
+ * given indexfactory.
+ *
+ * Returns: A new #GstIndex instance.
+ */
+GstIndex*
+gst_index_factory_create (GstIndexFactory *factory)
+{
+  GstIndex *new = NULL;
+
+  g_return_val_if_fail (factory != NULL, NULL);
+
+  if (gst_plugin_feature_ensure_loaded (GST_PLUGIN_FEATURE (factory))) {
+    g_return_val_if_fail (factory->type != 0, NULL);
+
+    new = GST_INDEX (g_object_new(factory->type,NULL));
+  }
+
+  return new;
+}
+
+/**
+ * gst_index_factory_make:
+ * @name: the name of the factory used to create the instance
+ *
+ * Create a new #GstIndex instance from the 
+ * indexfactory with the given name.
+ *
+ * Returns: A new #GstIndex instance.
+ */
+GstIndex*
+gst_index_factory_make (const gchar *name)
+{
+  GstIndexFactory *factory;
+
+  g_return_val_if_fail (name != NULL, NULL);
+
+  factory = gst_index_factory_find (name);
+
+  if (factory == NULL)
+    return NULL;
+
+  return gst_index_factory_create (factory);
+}
+
diff --git a/gst/gstindex.h b/gst/gstindex.h
new file mode 100644 (file)
index 0000000..3fa7547
--- /dev/null
@@ -0,0 +1,249 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *                    2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * gstindex.h: Header for GstIndex, base class to handle efficient
+ *             storage or caching of seeking information.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_INDEX_H__
+#define __GST_INDEX_H__
+
+#include <gst/gstobject.h>
+#include <gst/gstformat.h>
+#include <gst/gstpluginfeature.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_INDEX         (gst_index_get_type ())
+#define GST_INDEX(obj)         (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INDEX, GstIndex))
+#define GST_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INDEX, GstIndexClass))
+#define GST_IS_INDEX(obj)      (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INDEX))
+#define GST_IS_INDEX_CLASS(obj)        (GST_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INDEX))
+
+typedef struct _GstIndexEntry GstIndexEntry;
+typedef struct _GstIndexGroup GstIndexGroup;
+typedef struct _GstIndex GstIndex;
+typedef struct _GstIndexClass GstIndexClass;
+
+typedef enum {
+  GST_INDEX_UNKNOWN,
+  GST_INDEX_CERTAIN,
+  GST_INDEX_FUZZY
+} GstIndexCertainty;
+
+typedef enum {
+  GST_INDEX_ENTRY_ID,
+  GST_INDEX_ENTRY_ASSOCIATION,
+  GST_INDEX_ENTRY_OBJECT,
+  GST_INDEX_ENTRY_FORMAT,
+} GstIndexEntryType;
+
+typedef enum {
+  GST_INDEX_LOOKUP_EXACT,
+  GST_INDEX_LOOKUP_BEFORE,
+  GST_INDEX_LOOKUP_AFTER,
+} GstIndexLookupMethod;
+
+#define GST_INDEX_NASSOCS(entry)               ((entry)->data.assoc.nassocs)
+#define GST_INDEX_ASSOC_FLAGS(entry)   ((entry)->data.assoc.flags)
+#define GST_INDEX_ASSOC_FORMAT(entry,i)        ((entry)->data.assoc.assocs[(i)].format)
+#define GST_INDEX_ASSOC_VALUE(entry,i) ((entry)->data.assoc.assocs[(i)].value)
+
+typedef struct _GstIndexAssociation GstIndexAssociation;
+
+struct _GstIndexAssociation {
+  GstFormat    format;
+  gint64       value;
+};
+
+typedef enum {
+  GST_ACCOCIATION_FLAG_NONE    = 0,
+  GST_ACCOCIATION_FLAG_KEY_UNIT = (1 << 0),
+} GstAssocFlags;
+
+#define GST_INDEX_FORMAT_FORMAT(entry) ((entry)->data.format.format)
+#define GST_INDEX_FORMAT_KEY(entry)    ((entry)->data.format.key)
+
+#define GST_INDEX_ID_DESCRIPTION(entry)        ((entry)->data.id.description)
+
+struct _GstIndexEntry {
+  GstIndexEntryType     type;
+  gint                  id;
+
+  union {
+    struct {
+      gchar            *description;
+    } id;
+    struct {
+      gint              nassocs;
+      GstIndexAssociation 
+                       *assocs;
+      GstAssocFlags     flags;
+    } assoc;
+    struct {
+      gchar            *key;
+      GType             type;
+      gpointer          object;
+    } object;
+    struct {
+      GstFormat                 format;
+      gchar            *key;
+    } format;
+  } data;
+};
+
+struct _GstIndexGroup {
+  /* unique ID of group in index */
+  gint groupnum;
+
+  /* list of entries */
+  GList *entries;
+
+  /* the certainty level of the group */
+  GstIndexCertainty certainty;
+
+  /* peer group that contains more certain entries */
+  gint peergroup;
+};
+
+typedef gboolean       (*GstIndexFilter)               (GstIndex *index, 
+                                                        GstIndexEntry *entry);
+
+typedef gboolean       (*GstIndexResolver)             (GstIndex *index, 
+                                                        GstObject *writer, 
+                                                        gint *writer_id,
+                                                        gchar **writer_string,
+                                                        gpointer user_data);
+struct _GstIndex {
+  GstObject             object;
+
+  GList                        *groups;
+  GstIndexGroup                *curgroup;
+  gint                  maxgroup;
+
+  GstIndexResolver      resolver;
+  gpointer              resolver_user_data;
+
+  GstIndexFilter        filter;
+  gpointer              filter_user_data;
+
+  GHashTable           *writers;
+  gint                  last_id;
+};
+
+struct _GstIndexClass {
+  GstObjectClass parent_class;
+
+  gboolean     (*resolve_writer)       (GstIndex *index, GstObject *writer, 
+                                        gint *writer_id, gchar **writer_string);
+
+  /* abstract methods */
+  void         (*add_entry)            (GstIndex *index, GstIndexEntry *entry);
+
+  GstIndexEntry* (*get_assoc_entry)    (GstIndex *index, gint id, 
+                                        GstIndexLookupMethod method,
+                                        GstFormat format, gint64 value,
+                                        GCompareDataFunc func,
+                                        gpointer user_data); 
+  /* signals */
+  void         (*entry_added)          (GstIndex *index, GstIndexEntry *entry);
+};
+
+GType                  gst_index_get_type              (void);
+GstIndex*              gst_index_new                   (void);
+
+gint                   gst_index_get_group             (GstIndex *index);
+gint                   gst_index_new_group             (GstIndex *index);
+gboolean               gst_index_set_group             (GstIndex *index, gint groupnum);
+
+void                   gst_index_set_certainty         (GstIndex *index, 
+                                                        GstIndexCertainty certainty);
+GstIndexCertainty      gst_index_get_certainty         (GstIndex *index);
+
+void                   gst_index_set_filter            (GstIndex *index, 
+                                                        GstIndexFilter filter, gpointer user_data);
+void                   gst_index_set_resolver          (GstIndex *index, 
+                                                        GstIndexResolver resolver, gpointer user_data);
+
+gboolean               gst_index_get_writer_id         (GstIndex *index, GstObject *writer, gint *id);
+
+GstIndexEntry*         gst_index_add_format            (GstIndex *index, gint id, GstFormat format); 
+GstIndexEntry*         gst_index_add_association       (GstIndex *index, gint id, GstAssocFlags flags,
+                                                        GstFormat format, gint64 value, ...);
+GstIndexEntry*         gst_index_add_object            (GstIndex *index, gint id, gchar *key,
+                                                        GType type, gpointer object);
+GstIndexEntry*         gst_index_add_id                (GstIndex *index, gint id,
+                                                        gchar *description); 
+
+GstIndexEntry*         gst_index_get_assoc_entry       (GstIndex *index, gint id, 
+                                                        GstIndexLookupMethod method,
+                                                        GstFormat format, gint64 value);
+GstIndexEntry*         gst_index_get_assoc_entry_full  (GstIndex *index, gint id, 
+                                                        GstIndexLookupMethod method,
+                                                        GstFormat format, gint64 value,
+                                                        GCompareDataFunc func,
+                                                        gpointer user_data);
+
+/* working with index entries */
+void                   gst_index_entry_free            (GstIndexEntry *entry);
+gboolean               gst_index_entry_assoc_map       (GstIndexEntry *entry,
+                                                        GstFormat format, gint64 *value);
+/*
+ * creating indexs
+ *
+ */
+#define GST_TYPE_INDEX_FACTORY \
+  (gst_index_factory_get_type())
+#define GST_INDEX_FACTORY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_INDEX_FACTORY,GstIndexFactory))
+#define GST_INDEX_FACTORY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_INDEX_FACTORY,GstIndexFactoryClass))
+#define GST_IS_INDEX_FACTORY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_INDEX_FACTORY))
+#define GST_IS_INDEX_FACTORY_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_INDEX_FACTORY))
+
+typedef struct _GstIndexFactory GstIndexFactory;
+typedef struct _GstIndexFactoryClass GstIndexFactoryClass;
+
+struct _GstIndexFactory {
+  GstPluginFeature feature;
+           
+  gchar *longdesc;            /* long description of the index (well, don't overdo it..) */
+  GType type;                 /* unique GType of the index */
+};
+
+struct _GstIndexFactoryClass {
+  GstPluginFeatureClass parent; 
+};
+
+GType                  gst_index_factory_get_type      (void);
+
+GstIndexFactory*       gst_index_factory_new           (const gchar *name, 
+                                                        const gchar *longdesc, GType type);
+void                   gst_index_factory_destroy       (GstIndexFactory *factory);
+
+GstIndexFactory*       gst_index_factory_find          (const gchar *name);
+
+GstIndex*              gst_index_factory_create        (GstIndexFactory *factory);
+GstIndex*              gst_index_factory_make          (const gchar *name);
+
+G_END_DECLS
+
+#endif /* __GST_INDEX_H__ */