Imported Upstream version 0.10.23
[profile/ivi/gst-plugins-bad.git] / sys / applemedia / dynapi.c
1 /*
2  * Copyright (C) 2010 Ole André Vadla Ravnås <oravnas@cisco.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "dynapi.h"
21
22 #include "dynapi-internal.h"
23
24 #include <gmodule.h>
25 #include <gst/gst.h>
26
27 GST_DEBUG_CATEGORY (gst_dyn_api_debug);
28 #define GST_CAT_DEFAULT gst_dyn_api_debug
29
30 enum
31 {
32   PROP_0,
33   PROP_FILENAME
34 };
35
36 struct _GstDynApiPrivate
37 {
38   gchar *filename;
39   GModule *module;
40 };
41
42 G_DEFINE_TYPE (GstDynApi, gst_dyn_api, G_TYPE_OBJECT);
43
44 static void
45 gst_dyn_api_init (GstDynApi * self)
46 {
47   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_DYN_API,
48       GstDynApiPrivate);
49 }
50
51 static void
52 gst_dyn_api_dispose (GObject * object)
53 {
54   GstDynApi *self = GST_DYN_API_CAST (object);
55   GstDynApiPrivate *priv = self->priv;
56
57   if (priv->module != NULL) {
58     g_module_close (priv->module);
59     priv->module = NULL;
60   }
61
62   G_OBJECT_CLASS (gst_dyn_api_parent_class)->dispose (object);
63 }
64
65 static void
66 gst_dyn_api_finalize (GObject * object)
67 {
68   GstDynApi *self = GST_DYN_API_CAST (object);
69   GstDynApiPrivate *priv = self->priv;
70
71   g_free (priv->filename);
72
73   G_OBJECT_CLASS (gst_dyn_api_parent_class)->finalize (object);
74 }
75
76 static void
77 gst_dyn_api_get_property (GObject * object, guint prop_id,
78     GValue * value, GParamSpec * pspec)
79 {
80   GstDynApi *self = GST_DYN_API (object);
81
82   switch (prop_id) {
83     case PROP_FILENAME:
84       g_value_set_string (value, self->priv->filename);
85       break;
86     default:
87       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88       break;
89   }
90 }
91
92 static void
93 gst_dyn_api_set_property (GObject * object, guint prop_id,
94     const GValue * value, GParamSpec * pspec)
95 {
96   GstDynApi *self = GST_DYN_API (object);
97
98   switch (prop_id) {
99     case PROP_FILENAME:
100       g_free (self->priv->filename);
101       self->priv->filename = g_value_dup_string (value);
102       break;
103     default:
104       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
105       break;
106   }
107 }
108
109 static void
110 gst_dyn_api_class_init (GstDynApiClass * klass)
111 {
112   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
113
114   gobject_class->dispose = gst_dyn_api_dispose;
115   gobject_class->finalize = gst_dyn_api_finalize;
116   gobject_class->get_property = gst_dyn_api_get_property;
117   gobject_class->set_property = gst_dyn_api_set_property;
118
119   g_type_class_add_private (klass, sizeof (GstDynApiPrivate));
120
121   g_object_class_install_property (gobject_class, PROP_FILENAME,
122       g_param_spec_string ("filename", "Filename", "Filename", NULL,
123           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
124 }
125
126 gpointer
127 _gst_dyn_api_new (GType derived_type, const gchar * filename,
128     const GstDynSymSpec * symbols, GError ** error)
129 {
130   GstDynApi *api;
131   GstDynApiPrivate *priv;
132   guint i;
133   GArray *names_not_found;
134
135   api = g_object_new (derived_type, "filename", filename, NULL);
136   priv = api->priv;
137
138   priv->module = g_module_open (priv->filename, 0);
139   if (priv->module == NULL)
140     goto open_failed;
141
142   names_not_found = g_array_new (TRUE, FALSE, sizeof (gchar *));
143
144   for (i = 0; symbols[i].name != NULL; i++) {
145     const GstDynSymSpec *s = &symbols[i];
146     if (!g_module_symbol (priv->module, s->name,
147             (gpointer *) (((guint8 *) api) + s->offset)) && s->is_required) {
148       g_array_append_val (names_not_found, s->name);
149     }
150   }
151
152   if (names_not_found->len > 0)
153     goto one_or_more_name_not_found;
154
155   g_array_free (names_not_found, TRUE);
156
157   return api;
158
159   /* ERRORS */
160 open_failed:
161   {
162     gchar *basename;
163
164     basename = g_path_get_basename (filename);
165     g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
166         "failed to open %s", basename);
167     g_free (basename);
168
169     goto any_error;
170   }
171 one_or_more_name_not_found:
172   {
173     gchar *basename, *names_joined;
174
175     basename = g_path_get_basename (filename);
176     names_joined = g_strjoinv (", ", (gchar **) names_not_found->data);
177     g_set_error (error, GST_RESOURCE_ERROR, GST_RESOURCE_ERROR_FAILED,
178         "missing %u symbol%s in %s: %s",
179         names_not_found->len, (names_not_found->len == 1) ? "" : "s",
180         basename, names_joined);
181     g_free (names_joined);
182     g_free (basename);
183     g_array_free (names_not_found, TRUE);
184
185     goto any_error;
186   }
187 any_error:
188   {
189     g_object_unref (api);
190
191     return NULL;
192   }
193 }