]> sigrok.org Git - libsigrok.git/blobdiff - src/output/output.c
hameg-hmo: Make sure the enabled_channels list is empty before populating it
[libsigrok.git] / src / output / output.c
index 6406fcaceb3e5c75b9763982f14084c7c78297d9..3e432c9f0c7b82458621ef70ab0da8fa16b38364 100644 (file)
@@ -60,6 +60,7 @@ extern SR_PRIV struct sr_output_module output_gnuplot;
 extern SR_PRIV struct sr_output_module output_chronovu_la8;
 extern SR_PRIV struct sr_output_module output_csv;
 extern SR_PRIV struct sr_output_module output_analog;
+extern SR_PRIV struct sr_output_module output_wav;
 /* @endcond */
 
 static const struct sr_output_module *output_module_list[] = {
@@ -73,11 +74,12 @@ static const struct sr_output_module *output_module_list[] = {
        &output_vcd,
        &output_chronovu_la8,
        &output_analog,
+       &output_wav,
        NULL,
 };
 
 /**
- * Returns a NULL-terminated list of all the available output modules.
+ * Returns a NULL-terminated list of all available output modules.
  *
  * @since 0.4.0
  */
@@ -164,12 +166,12 @@ SR_API const struct sr_option *sr_output_options_get(const struct sr_output_modu
        if (!o || !o->options)
                return NULL;
 
-       return o->options(FALSE);
+       return o->options();
 }
 
 /**
  * After a call to sr_output_options_get(), this function cleans up all
- * the resources allocated by that call.
+ * resources allocated by that call.
  *
  * @since 0.4.0
  */
@@ -180,7 +182,7 @@ SR_API void sr_output_options_free(const struct sr_output_module *o)
        if (!o || !o->options)
                return;
 
-       for (opt = o->options(TRUE); opt->id; opt++) {
+       for (opt = o->options(); opt->id; opt++) {
                if (opt->def) {
                        g_variant_unref(opt->def);
                        opt->def = NULL;
@@ -210,14 +212,61 @@ SR_API const struct sr_output *sr_output_new(const struct sr_output_module *o,
                GHashTable *options, const struct sr_dev_inst *sdi)
 {
        struct sr_output *op;
+       struct sr_option *mod_opts;
+       const GVariantType *gvt;
+       GHashTable *new_opts;
+       GHashTableIter iter;
+       gpointer key, value;
+       int i;
 
        op = g_malloc(sizeof(struct sr_output));
        op->module = o;
        op->sdi = sdi;
-       if (op->module->init && op->module->init(op, options) != SR_OK) {
+
+       new_opts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+                       (GDestroyNotify)g_variant_unref);
+       if (o->options) {
+               mod_opts = o->options();
+               for (i = 0; mod_opts[i].id; i++) {
+                       if (options && g_hash_table_lookup_extended(options,
+                                       mod_opts[i].id, &key, &value)) {
+                               /* Pass option along. */
+                               gvt = g_variant_get_type(mod_opts[i].def);
+                               if (!g_variant_is_of_type(value, gvt)) {
+                                       sr_err("Invalid type for '%s' option.", key);
+                                       g_free(op);
+                                       return NULL;
+                               }
+                               g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
+                                               g_variant_ref(value));
+                       } else {
+                               /* Option not given: insert the default value. */
+                               g_hash_table_insert(new_opts, g_strdup(mod_opts[i].id),
+                                               g_variant_ref(mod_opts[i].def));
+                       }
+               }
+
+               /* Make sure no invalid options were given. */
+               if (options) {
+                       g_hash_table_iter_init(&iter, options);
+                       while (g_hash_table_iter_next(&iter, &key, &value)) {
+                               if (!g_hash_table_lookup(new_opts, key)) {
+                                       sr_err("Output module '%s' has no option '%s'", o->id, key);
+                                       g_hash_table_destroy(new_opts);
+                                       g_free(op);
+                                       return NULL;
+                               }
+                       }
+               }
+       }
+
+       if (op->module->init && op->module->init(op, new_opts) != SR_OK) {
+               g_hash_table_destroy(new_opts);
                g_free(op);
                op = NULL;
        }
+       if (new_opts)
+               g_hash_table_destroy(new_opts);
 
        return op;
 }