]> sigrok.org Git - libsigrok.git/commitdiff
Update bindings to use new output API.
authorMartin Ling <redacted>
Sat, 26 Jul 2014 15:03:25 +0000 (16:03 +0100)
committerMartin Ling <redacted>
Sat, 26 Jul 2014 15:03:25 +0000 (16:03 +0100)
bindings/cxx/classes.cpp
bindings/cxx/include/libsigrok/libsigrok.hpp
bindings/python/sigrok/core/classes.i
bindings/swig/classes.i

index 0d306a97848b444a04751a279a48188ea77cf913..67d490861b94503aacfd2298b01cda22bab93a5b 100644 (file)
@@ -41,8 +41,7 @@ static const char *valid_string(const char *input)
 }
 
 /** Helper function to convert between map<string, string> and GHashTable */
-
-static GHashTable *map_to_hash(map<string, string> input)
+static GHashTable *map_to_hash_string(map<string, string> input)
 {
        auto output = g_hash_table_new_full(
                g_str_hash, g_str_equal, g_free, g_free);
@@ -53,6 +52,19 @@ static GHashTable *map_to_hash(map<string, string> input)
     return output;
 }
 
+/** Helper function to convert between map<string, VariantBase> and GHashTable */
+static GHashTable *map_to_hash_variant(map<string, Glib::VariantBase> input)
+{
+       auto output = g_hash_table_new_full(
+               g_variant_hash, g_variant_equal, g_free,
+               (void (*)(void *))g_variant_unref);
+       for (auto entry : input)
+               g_hash_table_insert(output,
+                       g_strdup(entry.first.c_str()),
+                       entry.second.gobj_copy());
+    return output;
+}
+
 Error::Error(int result) : result(result)
 {
 }
@@ -85,10 +97,10 @@ Context::Context() :
                for (int i = 0; input_list[i]; i++)
                        input_formats[input_list[i]->id] =
                                new InputFormat(input_list[i]);
-       struct sr_output_format **output_list = sr_output_list();
+       const struct sr_output_module **output_list = sr_output_list();
        if (output_list)
                for (int i = 0; output_list[i]; i++)
-                       output_formats[output_list[i]->id] =
+                       output_formats[sr_output_id_get(output_list[i])] =
                                new OutputFormat(output_list[i]);
 }
 
@@ -1116,7 +1128,7 @@ shared_ptr<InputFileDevice> InputFormat::open_file(string filename,
                map<string, string> options)
 {
        auto input = g_new(struct sr_input, 1);
-       input->param = map_to_hash(options);
+       input->param = map_to_hash_string(options);
 
        /** Run initialisation. */
        check(structure->init(input, filename.c_str()));
@@ -1147,8 +1159,47 @@ void InputFileDevice::load()
        check(format->structure->loadfile(input, filename.c_str()));
 }
 
-OutputFormat::OutputFormat(struct sr_output_format *structure) :
-       StructureWrapper<Context, struct sr_output_format>(structure)
+Option::Option(const struct sr_option *structure,
+               shared_ptr<const struct sr_option> structure_array) :
+       structure(structure),
+       structure_array(structure_array)
+{
+}
+
+Option::~Option()
+{
+}
+
+string Option::get_id()
+{
+       return valid_string(structure->id);
+}
+
+string Option::get_name()
+{
+       return valid_string(structure->name);
+}
+
+string Option::get_description()
+{
+       return valid_string(structure->desc);
+}
+
+Glib::VariantBase Option::get_default_value()
+{
+       return Glib::VariantBase(structure->def, true);
+}
+
+vector<Glib::VariantBase> Option::get_values()
+{
+       vector<Glib::VariantBase> result;
+       for (auto l = structure->values; l; l = l->next)
+               result.push_back(Glib::VariantBase((GVariant *) l->data, true));
+       return result;
+}
+
+OutputFormat::OutputFormat(const struct sr_output_module *structure) :
+       StructureWrapper<Context, const struct sr_output_module>(structure)
 {
 }
 
@@ -1158,16 +1209,29 @@ OutputFormat::~OutputFormat()
 
 string OutputFormat::get_name()
 {
-       return valid_string(structure->id);
+       return valid_string(sr_output_id_get(structure));
 }
 
 string OutputFormat::get_description()
 {
-       return valid_string(structure->description);
+       return valid_string(sr_output_description_get(structure));
+}
+
+map<string, shared_ptr<Option>> OutputFormat::get_options()
+{
+       const struct sr_option *option = sr_output_options_get(structure);
+       auto option_array = shared_ptr<const struct sr_option>(
+               option, [=](const struct sr_option *) {
+                       sr_output_options_free(structure); });
+       map<string, shared_ptr<Option>> result;
+       for (; option->id; option++)
+               result[option->id] = shared_ptr<Option>(
+                       new Option(option, option_array), Option::Deleter());
+       return result;
 }
 
 shared_ptr<Output> OutputFormat::create_output(
-       shared_ptr<Device> device, map<string, string> options)
+       shared_ptr<Device> device, map<string, Glib::VariantBase> options)
 {
        return shared_ptr<Output>(
                new Output(
@@ -1177,16 +1241,15 @@ shared_ptr<Output> OutputFormat::create_output(
 }
 
 Output::Output(shared_ptr<OutputFormat> format,
-               shared_ptr<Device> device, map<string, string> options) :
+               shared_ptr<Device> device, map<string, Glib::VariantBase> options) :
        structure(sr_output_new(format->structure,
-               map_to_hash(options), device->structure)),
+               map_to_hash_variant(options), device->structure)),
        format(format), device(device), options(options)
 {
 }
 
 Output::~Output()
 {
-       g_hash_table_unref(structure->params);
        check(sr_output_free(structure));
 }
 
index 5435b83e0d24f4a9b516e122e800ffa851176af3..3063e3bdb41671964d44fb8fdff6ac0f54c0c087 100644 (file)
@@ -111,6 +111,7 @@ class SR_API QuantityFlag;
 class SR_API InputFileDevice;
 class SR_API Output;
 class SR_API DataType;
+class SR_API Option;
 
 /** Exception thrown when an error code is returned by any libsigrok call. */
 class SR_API Error: public exception
@@ -717,19 +718,52 @@ protected:
        friend class InputFormat;
 };
 
+/** An option used by an output format */
+class SR_API Option
+{
+public:
+       /** Short name of this option suitable for command line usage. */
+       string get_id();
+       /** Short name of this option suitable for GUI usage. */
+       string get_name();
+       /** Description of this option in a sentence. */
+       string get_description();
+       /** Default value for this option. */
+       Glib::VariantBase get_default_value();
+       /** Possible values for this option, if a limited set. */
+       vector<Glib::VariantBase> get_values();
+protected:
+       Option(const struct sr_option *structure,
+               shared_ptr<const struct sr_option> structure_array);
+       ~Option();
+       const struct sr_option *structure;
+       shared_ptr<const struct sr_option> structure_array;
+       /** Deleter needed to allow shared_ptr use with protected destructor. */
+       class Deleter
+       {
+       public:
+               void operator()(Option *option) { delete option; }
+       };
+       friend class Deleter;
+       friend class OutputFormat;
+};
+
 /** An output format supported by the library */
 class SR_API OutputFormat :
-       public StructureWrapper<Context, struct sr_output_format>
+       public StructureWrapper<Context, const struct sr_output_module>
 {
 public:
        /** Name of this output format. */
        string get_name();
        /** Description of this output format. */
        string get_description();
+       /** Options supported by this output format. */
+       map<string, shared_ptr<Option> > get_options();
        /** Create an output using this format. */
-       shared_ptr<Output> create_output(shared_ptr<Device> device, map<string, string> options = {});
+       shared_ptr<Output> create_output(shared_ptr<Device> device,
+               map<string, Glib::VariantBase> options = {});
 protected:
-       OutputFormat(struct sr_output_format *structure);
+       OutputFormat(const struct sr_output_module *structure);
        ~OutputFormat();
        friend class Context;
        friend class Output;
@@ -744,12 +778,12 @@ public:
 protected:
        Output(shared_ptr<OutputFormat> format, shared_ptr<Device> device);
        Output(shared_ptr<OutputFormat> format,
-               shared_ptr<Device> device, map<string, string> options);
+               shared_ptr<Device> device, map<string, Glib::VariantBase> options);
        ~Output();
-       struct sr_output *structure;
+       const struct sr_output *structure;
        const shared_ptr<OutputFormat> format;
        const shared_ptr<Device> device;
-       const map<string, string> options;
+       const map<string, Glib::VariantBase> options;
        /** Deleter needed to allow shared_ptr use with protected destructor. */
        class Deleter
        {
index 374996d56f86c15aa9c4079e95381dd411b45b5d..126991b7c247d58e8fd8ae75d7eabbee76f0e24c 100644 (file)
@@ -236,7 +236,7 @@ typedef guint pyg_flags_type;
 #include "libsigrok/libsigrok.hpp"
 
 /* Convert from a Python dict to a std::map<std::string, std::string> */
-std::map<std::string, std::string> dict_to_map(PyObject *dict)
+std::map<std::string, std::string> dict_to_map_string(PyObject *dict)
 {
     if (!PyDict_Check(dict))
         throw sigrok::Error(SR_ERR_ARG);
@@ -280,6 +280,51 @@ Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::Config
         throw sigrok::Error(SR_ERR_ARG);
 }
 
+/* Convert from a Python type to Glib::Variant, according to Option data type. */
+Glib::VariantBase python_to_variant_by_option(PyObject *input,
+    std::shared_ptr<sigrok::Option> option)
+{
+    GVariantType *type = option->get_default_value().get_type().gobj();
+
+    if (type == G_VARIANT_TYPE_UINT64 && PyInt_Check(input))
+        return Glib::Variant<guint64>::create(PyInt_AsLong(input));
+    if (type == G_VARIANT_TYPE_UINT64 && PyLong_Check(input))
+        return Glib::Variant<guint64>::create(PyLong_AsLong(input));
+    else if (type == G_VARIANT_TYPE_STRING && PyString_Check(input))
+        return Glib::Variant<std::string>::create(PyString_AsString(input));
+    else if (type == G_VARIANT_TYPE_BOOLEAN && PyBool_Check(input))
+        return Glib::Variant<bool>::create(input == Py_True);
+    else if (type == G_VARIANT_TYPE_DOUBLE && PyFloat_Check(input))
+        return Glib::Variant<double>::create(PyFloat_AsDouble(input));
+    else if (type == G_VARIANT_TYPE_INT32 && PyInt_Check(input))
+        return Glib::Variant<gint32>::create(PyInt_AsLong(input));
+    else
+        throw sigrok::Error(SR_ERR_ARG);
+}
+
+/* Convert from a Python dict to a std::map<std::string, std::string> */
+std::map<std::string, Glib::VariantBase> dict_to_map_options(PyObject *dict,
+    std::map<std::string, std::shared_ptr<sigrok::Option> > options)
+{
+    if (!PyDict_Check(dict))
+        throw sigrok::Error(SR_ERR_ARG);
+
+    std::map<std::string, Glib::VariantBase> output;
+
+    PyObject *py_key, *py_value;
+    Py_ssize_t pos = 0;
+
+    while (PyDict_Next(dict, &pos, &py_key, &py_value)) {
+        if (!PyString_Check(py_key))
+            throw sigrok::Error(SR_ERR_ARG);
+        auto key = PyString_AsString(py_key);
+        auto value = python_to_variant_by_option(py_value, options[key]);
+        output[key] = value;
+    }
+
+    return output;
+}
+
 %}
 
 /* Ignore these methods, we will override them below. */
@@ -327,7 +372,7 @@ Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::Config
 {
     std::shared_ptr<sigrok::InputFileDevice> _open_file_kwargs(std::string filename, PyObject *dict)
     {
-        return $self->open_file(filename, dict_to_map(dict));
+        return $self->open_file(filename, dict_to_map_string(dict));
     }
 }
 
@@ -345,7 +390,8 @@ Glib::VariantBase python_to_variant_by_key(PyObject *input, const sigrok::Config
     std::shared_ptr<sigrok::Output> _create_output_kwargs(
         std::shared_ptr<sigrok::Device> device, PyObject *dict)
     {
-        return $self->create_output(device, dict_to_map(dict));
+        return $self->create_output(device,
+            dict_to_map_options(dict, $self->get_options()));
     }
 }
 
index d0227d6be410653d90cc29d410ff912603354da6..fd9da099d9d274f57dad9195cff3cf8e55324fa8 100644 (file)
@@ -76,6 +76,7 @@ template< class T > class enable_shared_from_this;
 %shared_ptr(sigrok::Logic);
 %shared_ptr(sigrok::InputFormat);
 %shared_ptr(sigrok::InputFileDevice);
+%shared_ptr(sigrok::Option);
 %shared_ptr(sigrok::OutputFormat);
 %shared_ptr(sigrok::Output);
 %shared_ptr(sigrok::Trigger);
@@ -111,6 +112,16 @@ template< class T > class enable_shared_from_this;
 %template(ConfigMap)
     std::map<const sigrok::ConfigKey *, Glib::VariantBase>;
 
+%template(OptionVector)
+    std::vector<std::shared_ptr<sigrok::Option> >;
+%template(OptionMap)
+    std::map<std::string, std::shared_ptr<sigrok::Option> >;
+
+%template(VariantVector)
+    std::vector<Glib::VariantBase>;
+%template(VariantMap)
+    std::map<std::string, Glib::VariantBase>;
+
 %template(QuantityFlagVector)
     std::vector<const sigrok::QuantityFlag *>;
 
@@ -145,6 +156,10 @@ typedef std::map<std::string, std::shared_ptr<sigrok::OutputFormat> >
     map_string_OutputFormat;
 typedef std::map<std::string, std::shared_ptr<sigrok::ChannelGroup> >
     map_string_ChannelGroup;
+typedef std::map<std::string, std::shared_ptr<sigrok::Option> >
+    map_string_Option;
+typedef std::map<std::string, Glib::VariantBase>
+    map_string_Variant;
 typedef std::map<const sigrok::ConfigKey *, Glib::VariantBase>
     map_ConfigKey_Variant;
 }
@@ -175,10 +190,24 @@ typedef std::map<const sigrok::ConfigKey *, Glib::VariantBase>
 %attributestring(sigrok::InputFormat,
     std::string, description, get_description);
 
+%attributestring(sigrok::Option,
+    std::string, id, get_id);
+%attributestring(sigrok::Option,
+    std::string, name, get_name);
+%attributestring(sigrok::Option,
+    std::string, description, get_description);
+/* Currently broken on Python due to some issue with variant typemaps. */
+/* %attributeval(sigrok::Option,
+    Glib::VariantBase, default_value, get_default_value); */
+%attributeval(sigrok::Option,
+    std::vector<Glib::VariantBase>, values, get_values);
+
 %attributestring(sigrok::OutputFormat,
     std::string, name, get_name);
 %attributestring(sigrok::OutputFormat,
     std::string, description, get_description);
+%attributeval(sigrok::OutputFormat,
+    map_string_Option, options, get_options);
 
 %attributestring(sigrok::Device, std::string, description, get_description);
 %attributestring(sigrok::Device, std::string, vendor, get_vendor);