summaryrefslogtreecommitdiff
path: root/sys/applemedia-nonpublic/dynapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/applemedia-nonpublic/dynapi.c')
-rw-r--r--sys/applemedia-nonpublic/dynapi.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/sys/applemedia-nonpublic/dynapi.c b/sys/applemedia-nonpublic/dynapi.c
new file mode 100644
index 000000000..2317f80d2
--- /dev/null
+++ b/sys/applemedia-nonpublic/dynapi.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010 Ole André Vadla Ravnås <oleavr@soundrop.com>
+ *
+ * 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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "dynapi.h"
+
+#include "dynapi-internal.h"
+
+#include <gmodule.h>
+#include <gst/gst.h>
+
+GST_DEBUG_CATEGORY (gst_dyn_api_debug);
+#define GST_CAT_DEFAULT gst_dyn_api_debug
+
+enum
+{
+ PROP_0,
+ PROP_FILENAME
+};
+
+struct _GstDynApiPrivate
+{
+ gchar *filename;
+ GModule *module;
+};
+
+G_DEFINE_TYPE (GstDynApi, gst_dyn_api, G_TYPE_OBJECT);
+
+static void
+gst_dyn_api_init (GstDynApi * self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_DYN_API,
+ GstDynApiPrivate);
+}
+
+static void
+gst_dyn_api_dispose (GObject * object)
+{
+ GstDynApi *self = GST_DYN_API_CAST (object);
+ GstDynApiPrivate *priv = self->priv;
+
+ if (priv->module != NULL) {
+ g_module_close (priv->module);
+ priv->module = NULL;
+ }
+
+ G_OBJECT_CLASS (gst_dyn_api_parent_class)->dispose (object);
+}
+
+static void
+gst_dyn_api_finalize (GObject * object)
+{
+ GstDynApi *self = GST_DYN_API_CAST (object);
+ GstDynApiPrivate *priv = self->priv;
+
+ g_free (priv->filename);
+
+ G_OBJECT_CLASS (gst_dyn_api_parent_class)->finalize (object);
+}
+
+static void
+gst_dyn_api_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstDynApi *self = GST_DYN_API (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_value_set_string (value, self->priv->filename);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_dyn_api_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstDynApi *self = GST_DYN_API (object);
+
+ switch (prop_id) {
+ case PROP_FILENAME:
+ g_free (self->priv->filename);
+ self->priv->filename = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_dyn_api_class_init (GstDynApiClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = gst_dyn_api_dispose;
+ gobject_class->finalize = gst_dyn_api_finalize;
+ gobject_class->get_property = gst_dyn_api_get_property;
+ gobject_class->set_property = gst_dyn_api_set_property;
+
+ g_type_class_add_private (klass, sizeof (GstDynApiPrivate));
+
+ g_object_class_install_property (gobject_class, PROP_FILENAME,
+ g_param_spec_string ("filename", "Filename", "Filename", NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+gpointer
+_gst_dyn_api_new (GType derived_type, const gchar * filename,
+ const GstDynSymSpec * symbols, GError ** error)
+{
+ GstDynApi *api;
+ GstDynApiPrivate *priv;
+ guint i;
+ GArray *names_not_found;
+
+ api = g_object_new (derived_type, "filename", filename, NULL);
+ priv = api->priv;
+
+ priv->module = g_module_open (priv->filename, 0);
+ if (priv->module == NULL)
+ goto open_failed;
+
+ names_not_found = g_array_new (TRUE, FALSE, sizeof (gchar *));
+
+ for (i = 0; symbols[i].name != NULL; i++) {
+ const GstDynSymSpec *s = &symbols[i];
+ if (!g_module_symbol (priv->module, s->name,
+ (gpointer *) (((guint8 *) api) + s->offset)) && s->is_required) {
+ g_array_append_val (names_not_found, s->name);
+ }
+ }
+
+ if (names_not_found->len > 0)
+ goto one_or_more_name_not_found;
+
+ g_array_free (names_not_found, TRUE);
+
+ return api;
+
+ /* ERRORS */
+open_failed:
+ {
+ gchar *basename;
+
+ basename = g_path_get_basename (filename);
+ g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
+ "failed to open %s", basename);
+ g_free (basename);
+
+ goto any_error;
+ }
+one_or_more_name_not_found:
+ {
+ gchar *basename, *names_joined;
+
+ basename = g_path_get_basename (filename);
+ names_joined = g_strjoinv (", ", (gchar **) names_not_found->data);
+ g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
+ "missing %u symbol%s in %s: %s",
+ names_not_found->len, (names_not_found->len == 1) ? "" : "s",
+ basename, names_joined);
+ g_free (names_joined);
+ g_free (basename);
+ g_array_free (names_not_found, TRUE);
+
+ goto any_error;
+ }
+any_error:
+ {
+ g_object_unref (api);
+
+ return NULL;
+ }
+}