libsigrok  0.4.0
sigrok hardware access and backend library
transform.c
Go to the documentation of this file.
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2014 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2015 Uwe Hermann <uwe@hermann-uwe.de>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 #include <string.h>
23 #include <libsigrok/libsigrok.h>
24 #include "libsigrok-internal.h"
25 
26 /** @cond PRIVATE */
27 #define LOG_PREFIX "transform"
28 /** @endcond */
29 
30 /**
31  * @file
32  *
33  * Transform module handling.
34  */
35 
36 /**
37  * @defgroup grp_transform Transform modules
38  *
39  * Transform module handling.
40  *
41  * @{
42  */
43 
44 /** @cond PRIVATE */
45 extern SR_PRIV struct sr_transform_module transform_nop;
46 extern SR_PRIV struct sr_transform_module transform_scale;
47 extern SR_PRIV struct sr_transform_module transform_invert;
48 /* @endcond */
49 
50 static const struct sr_transform_module *transform_module_list[] = {
51  &transform_nop,
52  &transform_scale,
53  &transform_invert,
54  NULL,
55 };
56 
57 /**
58  * Returns a NULL-terminated list of all available transform modules.
59  *
60  * @since 0.4.0
61  */
62 SR_API const struct sr_transform_module **sr_transform_list(void)
63 {
64  return transform_module_list;
65 }
66 
67 /**
68  * Returns the specified transform module's ID.
69  *
70  * @since 0.4.0
71  */
72 SR_API const char *sr_transform_id_get(const struct sr_transform_module *tmod)
73 {
74  if (!tmod) {
75  sr_err("Invalid transform module NULL!");
76  return NULL;
77  }
78 
79  return tmod->id;
80 }
81 
82 /**
83  * Returns the specified transform module's name.
84  *
85  * @since 0.4.0
86  */
87 SR_API const char *sr_transform_name_get(const struct sr_transform_module *tmod)
88 {
89  if (!tmod) {
90  sr_err("Invalid transform module NULL!");
91  return NULL;
92  }
93 
94  return tmod->name;
95 }
96 
97 /**
98  * Returns the specified transform module's description.
99  *
100  * @since 0.4.0
101  */
102 SR_API const char *sr_transform_description_get(const struct sr_transform_module *tmod)
103 {
104  if (!tmod) {
105  sr_err("Invalid transform module NULL!");
106  return NULL;
107  }
108 
109  return tmod->desc;
110 }
111 
112 /**
113  * Return the transform module with the specified ID, or NULL if no module
114  * with that ID is found.
115  *
116  * @since 0.4.0
117  */
118 SR_API const struct sr_transform_module *sr_transform_find(const char *id)
119 {
120  int i;
121 
122  for (i = 0; transform_module_list[i]; i++) {
123  if (!strcmp(transform_module_list[i]->id, id))
124  return transform_module_list[i];
125  }
126 
127  return NULL;
128 }
129 
130 /**
131  * Returns a NULL-terminated array of struct sr_option, or NULL if the
132  * module takes no options.
133  *
134  * Each call to this function must be followed by a call to
135  * sr_transform_options_free().
136  *
137  * @since 0.4.0
138  */
139 SR_API const struct sr_option **sr_transform_options_get(const struct sr_transform_module *tmod)
140 {
141  const struct sr_option *mod_opts, **opts;
142  int size, i;
143 
144  if (!tmod || !tmod->options)
145  return NULL;
146 
147  mod_opts = tmod->options();
148 
149  for (size = 0; mod_opts[size].id; size++)
150  ;
151  opts = g_malloc((size + 1) * sizeof(struct sr_option *));
152 
153  for (i = 0; i < size; i++)
154  opts[i] = &mod_opts[i];
155  opts[i] = NULL;
156 
157  return opts;
158 }
159 
160 /**
161  * After a call to sr_transform_options_get(), this function cleans up all
162  * resources returned by that call.
163  *
164  * @since 0.4.0
165  */
166 SR_API void sr_transform_options_free(const struct sr_option **options)
167 {
168  int i;
169 
170  if (!options)
171  return;
172 
173  for (i = 0; options[i]; i++) {
174  if (options[i]->def) {
175  g_variant_unref(options[i]->def);
176  ((struct sr_option *)options[i])->def = NULL;
177  }
178 
179  if (options[i]->values) {
180  g_slist_free_full(options[i]->values, (GDestroyNotify)g_variant_unref);
181  ((struct sr_option *)options[i])->values = NULL;
182  }
183  }
184  g_free(options);
185 }
186 
187 /**
188  * Create a new transform instance using the specified transform module.
189  *
190  * <code>options</code> is a *GHashTable with the keys corresponding with
191  * the module options' <code>id</code> field. The values should be GVariant
192  * pointers with sunk * references, of the same GVariantType as the option's
193  * default value.
194  *
195  * The sr_dev_inst passed in can be used by the instance to determine
196  * channel names, samplerate, and so on.
197  *
198  * @since 0.4.0
199  */
200 SR_API const struct sr_transform *sr_transform_new(const struct sr_transform_module *tmod,
201  GHashTable *options, const struct sr_dev_inst *sdi)
202 {
203  struct sr_transform *t;
204  const struct sr_option *mod_opts;
205  const GVariantType *gvt;
206  GHashTable *new_opts;
207  GHashTableIter iter;
208  gpointer key, value;
209  int i;
210 
211  t = g_malloc(sizeof(struct sr_transform));
212  t->module = tmod;
213  t->sdi = sdi;
214 
215  new_opts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
216  (GDestroyNotify)g_variant_unref);
217  if (tmod->options) {
218  mod_opts = tmod->options();
219  for (i = 0; mod_opts[i].id; i++) {
220  if (options && g_hash_table_lookup_extended(options,
221  mod_opts[i].id, &key, &value)) {
222  /* Pass option along. */
223  gvt = g_variant_get_type(mod_opts[i].def);
224  if (!g_variant_is_of_type(value, gvt)) {
225  sr_err("Invalid type for '%s' option.",
226  (char *)key);
227  g_free(t);
228  return NULL;
229  }
230  g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
231  g_variant_ref(value));
232  } else {
233  /* Option not given: insert the default value. */
234  g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
235  g_variant_ref(mod_opts[i].def));
236  }
237  }
238 
239  /* Make sure no invalid options were given. */
240  if (options) {
241  g_hash_table_iter_init(&iter, options);
242  while (g_hash_table_iter_next(&iter, &key, &value)) {
243  if (!g_hash_table_lookup(new_opts, key)) {
244  sr_err("Transform module '%s' has no option '%s'.",
245  tmod->id, (char *)key);
246  g_hash_table_destroy(new_opts);
247  g_free(t);
248  return NULL;
249  }
250  }
251  }
252  }
253 
254  if (t->module->init && t->module->init(t, new_opts) != SR_OK) {
255  g_free(t);
256  t = NULL;
257  }
258  if (new_opts)
259  g_hash_table_destroy(new_opts);
260 
261  /* Add the transform to the session's list of transforms. */
262  sdi->session->transforms = g_slist_append(sdi->session->transforms, t);
263 
264  return t;
265 }
266 
267 /**
268  * Free the specified transform instance and all associated resources.
269  *
270  * @since 0.4.0
271  */
272 SR_API int sr_transform_free(const struct sr_transform *t)
273 {
274  int ret;
275 
276  if (!t)
277  return SR_ERR_ARG;
278 
279  ret = SR_OK;
280  if (t->module->cleanup)
281  ret = t->module->cleanup((struct sr_transform *)t);
282  g_free((gpointer)t);
283 
284  return ret;
285 }
286 
287 /** @} */
The public libsigrok header file to be used by frontends.
const struct sr_transform_module ** sr_transform_list(void)
Returns a NULL-terminated list of all available transform modules.
Definition: transform.c:62
const struct sr_option ** sr_transform_options_get(const struct sr_transform_module *tmod)
Returns a NULL-terminated array of struct sr_option, or NULL if the module takes no options...
Definition: transform.c:139
void sr_transform_options_free(const struct sr_option **options)
After a call to sr_transform_options_get(), this function cleans up all resources returned by that ca...
Definition: transform.c:166
const char * sr_transform_name_get(const struct sr_transform_module *tmod)
Returns the specified transform module's name.
Definition: transform.c:87
const char * id
Definition: libsigrok.h:549
const char * sr_transform_description_get(const struct sr_transform_module *tmod)
Returns the specified transform module's description.
Definition: transform.c:102
#define SR_API
Definition: libsigrok.h:121
No error.
Definition: libsigrok.h:67
GVariant * def
Definition: libsigrok.h:555
GSList * values
Definition: libsigrok.h:557
Generic option struct used by various subsystems.
Definition: libsigrok.h:547
const struct sr_transform * sr_transform_new(const struct sr_transform_module *tmod, GHashTable *options, const struct sr_dev_inst *sdi)
Create a new transform instance using the specified transform module.
Definition: transform.c:200
const char * sr_transform_id_get(const struct sr_transform_module *tmod)
Returns the specified transform module's ID.
Definition: transform.c:72
const struct sr_transform_module * sr_transform_find(const char *id)
Return the transform module with the specified ID, or NULL if no module with that ID is found...
Definition: transform.c:118
#define SR_PRIV
Definition: libsigrok.h:128
Function argument error.
Definition: libsigrok.h:70
int sr_transform_free(const struct sr_transform *t)
Free the specified transform instance and all associated resources.
Definition: transform.c:272