Esempio n. 1
0
    def value_integer(self, subject, subject_name):
        value = 0

        if is_integer(lilv.lilv_node_as_string(subject)):
            value = lilv.lilv_node_as_int(subject)

        else:
            value = lilv.lilv_node_as_float(subject)
            if fmod(value, 1.0) == 0.0:
                self.warnings.append("port '%s' has integer property but %s value is float" % (self.portname, subject_name))
            else:
                self.register_error("has integer property but %s value has non-zero decimals", subject_name)
            value = int(value)

        return value
Esempio n. 2
0
    def fill_port_info(port):
        # base data
        portname = lilv.lilv_node_as_string(port.get_name()) or ""

        if not portname:
            portname = "_%i" % index
            errors.append("port with index %i has no name" % index)

        portsymbol = lilv.lilv_node_as_string(port.get_symbol()) or ""

        if not portsymbol:
            portsymbol = "_%i" % index
            errors.append("port with index %i has no symbol" % index)

        # check for duplicate names
        if portname in portsymbols:
            warnings.append("port name '%s' is not unique" % portname)
        else:
            portnames.append(portname)

        # check for duplicate symbols
        if portsymbol in portsymbols:
            errors.append("port symbol '%s' is not unique" % portsymbol)
        else:
            portsymbols.append(portsymbol)

        # short name
        psname = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.shortname.me))

        if psname is not None:
            psname = lilv.lilv_node_as_string(psname) or ""

        if not psname:
            psname = get_short_port_name(portname)
            warnings.append("port '%s' has no short name" % portname)

        elif len(psname) > 16:
            psname = psname[:16]
            errors.append("port '%s' short name has more than 16 characters" % portname)

        # port types
        types = [typ.rsplit("#",1)[-1].replace("Port","",1) for typ in get_port_data(port, ns_rdf.type_)]

        if "Atom" in types \
            and port.supports_event(ns_midi.MidiEvent.me) \
            and lilv.Nodes(port.get_value(ns_atom.bufferType.me)).get_first() == ns_atom.Sequence:
                types.append("MIDI")

        # port properties
        properties = [typ.rsplit("#",1)[-1] for typ in get_port_data(port, ns_lv2core.portProperty)]

        # data
        ranges      = {}
        scalepoints = []

        # unit block
        ulabel  = ""
        urender = ""
        usymbol = ""

        # control and cv must contain ranges, might contain scale points
        if "Control" in types or "CV" in types:
            isInteger = "integer" in properties

            if isInteger and "CV" in types:
                errors.append("port '%s' has integer property and CV type" % portname)

            xdefault = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.default.me))
            xminimum = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.minimum.me))
            xmaximum = lilv.lilv_nodes_get_first(port.get_value(ns_lv2core.maximum.me))

            if xminimum is not None and xmaximum is not None:
                if isInteger:
                    if is_integer(lilv.lilv_node_as_string(xminimum)):
                        ranges['minimum'] = lilv.lilv_node_as_int(xminimum)
                    else:
                        ranges['minimum'] = lilv.lilv_node_as_float(xminimum)
                        if fmod(ranges['minimum'], 1.0) == 0.0:
                            warnings.append("port '%s' has integer property but minimum value is float" % portname)
                        else:
                            errors.append("port '%s' has integer property but minimum value has non-zero decimals" % portname)
                        ranges['minimum'] = int(ranges['minimum'])

                    if is_integer(lilv.lilv_node_as_string(xmaximum)):
                        ranges['maximum'] = lilv.lilv_node_as_int(xmaximum)
                    else:
                        ranges['maximum'] = lilv.lilv_node_as_float(xmaximum)
                        if fmod(ranges['maximum'], 1.0) == 0.0:
                            warnings.append("port '%s' has integer property but maximum value is float" % portname)
                        else:
                            errors.append("port '%s' has integer property but maximum value has non-zero decimals" % portname)
                        ranges['maximum'] = int(ranges['maximum'])

                else:
                    ranges['minimum'] = lilv.lilv_node_as_float(xminimum)
                    ranges['maximum'] = lilv.lilv_node_as_float(xmaximum)

                    if is_integer(lilv.lilv_node_as_string(xminimum)):
                        warnings.append("port '%s' minimum value is an integer" % portname)

                    if is_integer(lilv.lilv_node_as_string(xmaximum)):
                        warnings.append("port '%s' maximum value is an integer" % portname)

                if ranges['minimum'] >= ranges['maximum']:
                    ranges['maximum'] = ranges['minimum'] + (1 if isInteger else 0.1)
                    errors.append("port '%s' minimum value is equal or higher than its maximum" % portname)

                if xdefault is not None:
                    if isInteger:
                        if is_integer(lilv.lilv_node_as_string(xdefault)):
                            ranges['default'] = lilv.lilv_node_as_int(xdefault)
                        else:
                            ranges['default'] = lilv.lilv_node_as_float(xdefault)
                            if fmod(ranges['default'], 1.0) == 0.0:
                                warnings.append("port '%s' has integer property but default value is float" % portname)
                            else:
                                errors.append("port '%s' has integer property but default value has non-zero decimals" % portname)
                            ranges['default'] = int(ranges['default'])
                    else:
                        ranges['default'] = lilv.lilv_node_as_float(xdefault)

                        if is_integer(lilv.lilv_node_as_string(xdefault)):
                            warnings.append("port '%s' default value is an integer" % portname)

                    testmin = ranges['minimum']
                    testmax = ranges['maximum']

                    if "sampleRate" in properties:
                        testmin *= 48000
                        testmax *= 48000

                    if not (testmin <= ranges['default'] <= testmax):
                        ranges['default'] = ranges['minimum']
                        errors.append("port '%s' default value is out of bounds" % portname)

                else:
                    ranges['default'] = ranges['minimum']

                    if "Input" in types:
                        errors.append("port '%s' is missing default value" % portname)

            else:
                if isInteger:
                    ranges['minimum'] = 0
                    ranges['maximum'] = 1
                    ranges['default'] = 0
                else:
                    ranges['minimum'] = -1.0 if "CV" in types else 0.0
                    ranges['maximum'] = 1.0
                    ranges['default'] = 0.0

                if "CV" not in types:
                    errors.append("port '%s' is missing value ranges" % portname)

            nodes = port.get_scale_points()

            if nodes is not None:
                it = lilv.lilv_scale_points_begin(nodes)
                while not lilv.lilv_scale_points_is_end(nodes, it):
                    sp = lilv.lilv_scale_points_get(nodes, it)
                    it = lilv.lilv_scale_points_next(nodes, it)

                    if sp is None:
                        continue

                    label = lilv.lilv_scale_point_get_label(sp)
                    value = lilv.lilv_scale_point_get_value(sp)

                    if label is None:
                        errors.append("a port scalepoint is missing its label")
                        continue

                    label = lilv.lilv_node_as_string(label) or ""

                    if not label:
                        errors.append("a port scalepoint is missing its label")
                        continue

                    if value is None:
                        errors.append("port scalepoint '%s' is missing its value" % label)
                        continue

                    if isInteger:
                        if is_integer(lilv.lilv_node_as_string(value)):
                            value = lilv.lilv_node_as_int(value)
                        else:
                            value = lilv.lilv_node_as_float(value)
                            if fmod(value, 1.0) == 0.0:
                                warnings.append("port '%s' has integer property but scalepoint '%s' value is float" % (portname, label))
                            else:
                                errors.append("port '%s' has integer property but scalepoint '%s' value has non-zero decimals" % (portname, label))
                            value = int(value)
                    else:
                        if is_integer(lilv.lilv_node_as_string(value)):
                            warnings.append("port '%s' scalepoint '%s' value is an integer" % (portname, label))
                        value = lilv.lilv_node_as_float(value)

                    if ranges['minimum'] <= value <= ranges['maximum']:
                        scalepoints.append({'label': label, 'value': value})
                    else:
                        errors.append(("port scalepoint '%s' has an out-of-bounds value:\n" % label) +
                                      ("%d < %d < %d" if isInteger else "%f < %f < %f") % (ranges['minimum'], value, ranges['maximum']))

            if "enumeration" in properties and len(scalepoints) <= 1:
                errors.append("port '%s' wants to use enumeration but doesn't have enough values" % portname)
                properties.remove("enumeration")

        # control ports might contain unit
        if "Control" in types:
            # unit
            uunit = lilv.lilv_nodes_get_first(port.get_value(ns_units.unit.me))

            if uunit is not None:
                uuri = lilv.lilv_node_as_uri(uunit)

                # using pre-existing lv2 unit
                if uuri is not None and uuri.startswith("http://lv2plug.in/ns/"):
                    uuri  = uuri.replace("http://lv2plug.in/ns/extensions/units#","",1)
                    alnum = uuri.isalnum()

                    if not alnum:
                        errors.append("port '%s' has wrong lv2 unit uri" % portname)
                        uuri = uuri.rsplit("#",1)[-1].rsplit("/",1)[-1]

                    ulabel, urender, usymbol = get_port_unit(uuri)

                    if alnum and not (ulabel and urender and usymbol):
                        errors.append("port '%s' has unknown lv2 unit (our bug?, data is '%s', '%s', '%s')" % (portname,
                                                                                                               ulabel,
                                                                                                               urender,
                                                                                                               usymbol))

                # using custom unit
                else:
                    xlabel  = world.find_nodes(uunit, ns_rdfs  .label.me, None).get_first()
                    xrender = world.find_nodes(uunit, ns_units.render.me, None).get_first()
                    xsymbol = world.find_nodes(uunit, ns_units.symbol.me, None).get_first()

                    if xlabel.me is not None:
                        ulabel = xlabel.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no label" % portname)

                    if xrender.me is not None:
                        urender = xrender.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no render" % portname)

                    if xsymbol.me is not None:
                        usymbol = xsymbol.as_string()
                    else:
                        errors.append("port '%s' has custom unit with no symbol" % portname)

        return (types, {
            'name'   : portname,
            'symbol' : portsymbol,
            'ranges' : ranges,
            'units'  : {
                'label' : ulabel,
                'render': urender,
                'symbol': usymbol,
            } if "Control" in types and ulabel and urender and usymbol else {},
            'designation': (get_port_data(port, ns_lv2core.designation) or [None])[0],
            'properties' : properties,
            'rangeSteps' : (get_port_data(port, ns_mod.rangeSteps) or get_port_data(port, ns_pprops.rangeSteps) or [None])[0],
            "scalePoints": scalepoints,
            'shortname'  : psname,
        })
Esempio n. 3
0
def get_pedalboard_info(bundle):
    # lilv wants the last character as the separator
    if not bundle.endswith(os.sep):
        bundle += os.sep

    # Create our own unique lilv world
    # We'll load a single bundle and get all plugins from it
    world = lilv.World()

    # this is needed when loading specific bundles instead of load_all
    # (these functions are not exposed via World yet)
    lilv.lilv_world_load_specifications(world.me)
    lilv.lilv_world_load_plugin_classes(world.me)

    # convert bundle string into a lilv node
    bundlenode = lilv.lilv_new_file_uri(world.me, None, bundle)

    # load the bundle
    world.load_bundle(bundlenode)

    # free bundlenode, no longer needed
    lilv.lilv_node_free(bundlenode)

    # get all plugins in the bundle
    plugins = world.get_all_plugins()

    # make sure the bundle includes 1 and only 1 plugin (the pedalboard)
    if plugins.size() != 1:
        raise Exception('get_pedalboard_info(%s) - bundle has 0 or > 1 plugin'.format(bundle))

    # no indexing in python-lilv yet, just get the first item
    plugin = None
    for p in plugins:
        plugin = p
        break

    if plugin is None:
        raise Exception('get_pedalboard_info(%s) - failed to get plugin, you are using an old lilv!'.format(bundle))

    # define the needed stuff
    ns_rdf      = NS(world, lilv.LILV_NS_RDF)
    ns_lv2core  = NS(world, lilv.LILV_NS_LV2)
    ns_ingen    = NS(world, "http://drobilla.net/ns/ingen#")
    ns_modpedal = NS(world, "http://moddevices.com/ns/modpedal#")

    # check if the plugin is a pedalboard
    def fill_in_type(node):
        return node.as_string()
    plugin_types = [i for i in LILV_FOREACH(plugin.get_value(ns_rdf.type_), fill_in_type)]

    if "http://moddevices.com/ns/modpedal#Pedalboard" not in plugin_types:
        raise Exception('get_pedalboard_info(%s) - plugin has no mod:Pedalboard type'.format(bundle))

    # let's get all the info now
    ingenarcs   = []
    ingenblocks = []

    info = {
        'name'  : plugin.get_name().as_string(),
        'uri'   : plugin.get_uri().as_string(),
        'author': plugin.get_author_name().as_string() or "", # Might be empty
        'hardware': {
            # we save this info later
            'audio': {
                'ins' : 0,
                'outs': 0
             },
            'cv': {
                'ins' : 0,
                'outs': 0
             },
            'midi': {
                'ins' : 0,
                'outs': 0
             }
        },
        'size': {
            'width' : plugin.get_value(ns_modpedal.width).get_first().as_int(),
            'height': plugin.get_value(ns_modpedal.height).get_first().as_int(),
        },
        'screenshot' : os.path.basename(plugin.get_value(ns_modpedal.screenshot).get_first().as_string()),
        'thumbnail'  : os.path.basename(plugin.get_value(ns_modpedal.thumbnail).get_first().as_string()),
        'connections': [], # we save this info later
        'plugins'    : []  # we save this info later
    }

    # connections
    arcs = plugin.get_value(ns_ingen.arc)
    it = arcs.begin()
    while not arcs.is_end(it):
        arc = arcs.get(it)
        it  = arcs.next(it)

        if arc.me is None:
            continue

        head = lilv.lilv_world_get(world.me, arc.me, ns_ingen.head.me, None)
        tail = lilv.lilv_world_get(world.me, arc.me, ns_ingen.tail.me, None)

        if head is None or tail is None:
            continue

        ingenarcs.append({
            "source": lilv.lilv_uri_to_path(lilv.lilv_node_as_string(tail)).replace(bundle,"",1),
            "target": lilv.lilv_uri_to_path(lilv.lilv_node_as_string(head)).replace(bundle,"",1)
        })

    # hardware ports
    handled_port_uris = []
    ports = plugin.get_value(ns_lv2core.port)
    it = ports.begin()
    while not ports.is_end(it):
        port = ports.get(it)
        it   = ports.next(it)

        if port.me is None:
            continue

        # check if we already handled this port
        port_uri = port.as_uri()
        if port_uri in handled_port_uris:
            continue
        handled_port_uris.append(port_uri)

        # get types
        port_types = lilv.lilv_world_find_nodes(world.me, port.me, ns_rdf.type_.me, None)

        if port_types is None:
            continue

        portDir  = "" # input or output
        portType = "" # atom, audio or cv

        it2 = lilv.lilv_nodes_begin(port_types)
        while not lilv.lilv_nodes_is_end(port_types, it2):
            port_type = lilv.lilv_nodes_get(port_types, it2)
            it2 = lilv.lilv_nodes_next(port_types, it2)

            if port_type is None:
                continue

            port_type_uri = lilv.lilv_node_as_uri(port_type)

            if port_type_uri == "http://lv2plug.in/ns/lv2core#InputPort":
                portDir = "input"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#OutputPort":
                portDir = "output"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#AudioPort":
                portType = "audio"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#CVPort":
                portType = "cv"
            elif port_type_uri == "http://lv2plug.in/ns/ext/atom#AtomPort":
                portType = "atom"

        if not (portDir or portType):
            continue

        if portType == "audio":
            if portDir == "input":
                info['hardware']['audio']['ins'] += 1
            else:
                info['hardware']['audio']['outs'] += 1

        elif portType == "atom":
            if portDir == "input":
                info['hardware']['midi']['ins'] += 1
            else:
                info['hardware']['midi']['outs'] += 1

        elif portType == "cv":
            if portDir == "input":
                info['hardware']['cv']['ins'] += 1
            else:
                info['hardware']['cv']['outs'] += 1

    # plugins
    blocks = plugin.get_value(ns_ingen.block)
    it = blocks.begin()
    while not blocks.is_end(it):
        block = blocks.get(it)
        it    = blocks.next(it)

        if block.me is None:
            continue

        protouri1 = lilv.lilv_world_get(world.me, block.me, ns_lv2core.prototype.me, None)
        protouri2 = lilv.lilv_world_get(world.me, block.me, ns_ingen.prototype.me, None)

        if protouri1 is not None:
            proto = protouri1
        elif protouri2 is not None:
            proto = protouri2
        else:
            continue

        uri = lilv.lilv_node_as_uri(proto)

        microver = lilv.lilv_world_get(world.me, block.me, ns_lv2core.microVersion.me, None)
        minorver = lilv.lilv_world_get(world.me, block.me, ns_lv2core.minorVersion.me, None)

        ingenblocks.append({
            "uri": uri,
            "x": lilv.lilv_node_as_float(lilv.lilv_world_get(world.me, block.me, ns_ingen.canvasX.me, None)),
            "y": lilv.lilv_node_as_float(lilv.lilv_world_get(world.me, block.me, ns_ingen.canvasY.me, None)),
            "microVersion": lilv.lilv_node_as_int(microver) if microver else 0,
            "minorVersion": lilv.lilv_node_as_int(minorver) if minorver else 0,
        })

    info['connections'] = ingenarcs
    info['plugins']     = ingenblocks

    return info
Esempio n. 4
0
def get_pedalboard_info(bundle):
    # lilv wants the last character as the separator
    bundle = os.path.abspath(bundle)
    if not bundle.endswith(os.sep):
        bundle += os.sep

    # Create our own unique lilv world
    # We'll load a single bundle and get all plugins from it
    world = lilv.World()

    # this is needed when loading specific bundles instead of load_all
    # (these functions are not exposed via World yet)
    lilv.lilv_world_load_specifications(world.me)
    lilv.lilv_world_load_plugin_classes(world.me)

    # convert bundle string into a lilv node
    bundlenode = lilv.lilv_new_file_uri(world.me, None, bundle)

    # load the bundle
    world.load_bundle(bundlenode)

    # free bundlenode, no longer needed
    lilv.lilv_node_free(bundlenode)

    # get all plugins in the bundle
    plugins = world.get_all_plugins()

    # make sure the bundle includes 1 and only 1 plugin (the pedalboard)
    if plugins.size() != 1:
        raise Exception(
            'get_pedalboard_info(%s) - bundle has 0 or > 1 plugin'.format(
                bundle))

    # no indexing in python-lilv yet, just get the first item
    plugin = None
    for p in plugins:
        plugin = p
        break

    if plugin is None:
        raise Exception(
            'get_pedalboard_info(%s) - failed to get plugin, you are using an old lilv!'
            .format(bundle))

    # define the needed stuff
    ns_rdf = NS(world, lilv.LILV_NS_RDF)
    ns_lv2core = NS(world, lilv.LILV_NS_LV2)
    ns_ingen = NS(world, "http://drobilla.net/ns/ingen#")
    ns_modpedal = NS(world, "http://moddevices.com/ns/modpedal#")

    # check if the plugin is a pedalboard
    def fill_in_type(node):
        return node.as_string()

    plugin_types = [
        i for i in LILV_FOREACH(plugin.get_value(ns_rdf.type_), fill_in_type)
    ]

    if "http://moddevices.com/ns/modpedal#Pedalboard" not in plugin_types:
        raise Exception(
            'get_pedalboard_info(%s) - plugin has no mod:Pedalboard type'.
            format(bundle))

    # let's get all the info now
    ingenarcs = []
    ingenblocks = []

    info = {
        'name':
        plugin.get_name().as_string(),
        'uri':
        plugin.get_uri().as_string(),
        'author':
        plugin.get_author_name().as_string() or "",  # Might be empty
        'hardware': {
            # we save this info later
            'audio': {
                'ins': 0,
                'outs': 0
            },
            'cv': {
                'ins': 0,
                'outs': 0
            },
            'midi': {
                'ins': 0,
                'outs': 0
            }
        },
        'size': {
            'width': plugin.get_value(ns_modpedal.width).get_first().as_int(),
            'height':
            plugin.get_value(ns_modpedal.height).get_first().as_int(),
        },
        'screenshot':
        os.path.basename(
            plugin.get_value(ns_modpedal.screenshot).get_first().as_string()
            or ""),
        'thumbnail':
        os.path.basename(
            plugin.get_value(ns_modpedal.thumbnail).get_first().as_string()
            or ""),
        'connections': [],  # we save this info later
        'plugins': []  # we save this info later
    }

    # connections
    arcs = plugin.get_value(ns_ingen.arc)
    it = arcs.begin()
    while not arcs.is_end(it):
        arc = arcs.get(it)
        it = arcs.next(it)

        if arc.me is None:
            continue

        head = lilv.lilv_world_get(world.me, arc.me, ns_ingen.head.me, None)
        tail = lilv.lilv_world_get(world.me, arc.me, ns_ingen.tail.me, None)

        if head is None or tail is None:
            continue

        ingenarcs.append({
            "source":
            lilv.lilv_uri_to_path(lilv.lilv_node_as_string(tail)).replace(
                bundle, "", 1),
            "target":
            lilv.lilv_uri_to_path(lilv.lilv_node_as_string(head)).replace(
                bundle, "", 1)
        })

    # hardware ports
    handled_port_uris = []
    ports = plugin.get_value(ns_lv2core.port)
    it = ports.begin()
    while not ports.is_end(it):
        port = ports.get(it)
        it = ports.next(it)

        if port.me is None:
            continue

        # check if we already handled this port
        port_uri = port.as_uri()
        if port_uri in handled_port_uris:
            continue
        if port_uri.endswith("/control_in") or port_uri.endswith(
                "/control_out"):
            continue
        handled_port_uris.append(port_uri)

        # get types
        port_types = lilv.lilv_world_find_nodes(world.me, port.me,
                                                ns_rdf.type_.me, None)

        if port_types is None:
            continue

        portDir = ""  # input or output
        portType = ""  # atom, audio or cv

        it2 = lilv.lilv_nodes_begin(port_types)
        while not lilv.lilv_nodes_is_end(port_types, it2):
            port_type = lilv.lilv_nodes_get(port_types, it2)
            it2 = lilv.lilv_nodes_next(port_types, it2)

            if port_type is None:
                continue

            port_type_uri = lilv.lilv_node_as_uri(port_type)

            if port_type_uri == "http://lv2plug.in/ns/lv2core#InputPort":
                portDir = "input"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#OutputPort":
                portDir = "output"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#AudioPort":
                portType = "audio"
            elif port_type_uri == "http://lv2plug.in/ns/lv2core#CVPort":
                portType = "cv"
            elif port_type_uri == "http://lv2plug.in/ns/ext/atom#AtomPort":
                portType = "atom"

        if not (portDir or portType):
            continue

        if portType == "audio":
            if portDir == "input":
                info['hardware']['audio']['ins'] += 1
            else:
                info['hardware']['audio']['outs'] += 1

        elif portType == "atom":
            if portDir == "input":
                info['hardware']['midi']['ins'] += 1
            else:
                info['hardware']['midi']['outs'] += 1

        elif portType == "cv":
            if portDir == "input":
                info['hardware']['cv']['ins'] += 1
            else:
                info['hardware']['cv']['outs'] += 1

    # plugins
    blocks = plugin.get_value(ns_ingen.block)
    it = blocks.begin()
    while not blocks.is_end(it):
        block = blocks.get(it)
        it = blocks.next(it)

        if block.me is None:
            continue

        protouri1 = lilv.lilv_world_get(world.me, block.me,
                                        ns_lv2core.prototype.me, None)
        protouri2 = lilv.lilv_world_get(world.me, block.me,
                                        ns_ingen.prototype.me, None)

        if protouri1 is not None:
            proto = protouri1
        elif protouri2 is not None:
            proto = protouri2
        else:
            continue

        instance = lilv.lilv_uri_to_path(lilv.lilv_node_as_string(
            block.me)).replace(bundle, "", 1)
        uri = lilv.lilv_node_as_uri(proto)

        enabled = lilv.lilv_world_get(world.me, block.me, ns_ingen.enabled.me,
                                      None)
        minorver = lilv.lilv_world_get(world.me, block.me,
                                       ns_lv2core.minorVersion.me, None)
        microver = lilv.lilv_world_get(world.me, block.me,
                                       ns_lv2core.microVersion.me, None)

        ingenblocks.append({
            "instance":
            instance,
            "uri":
            uri,
            "x":
            lilv.lilv_node_as_float(
                lilv.lilv_world_get(world.me, block.me, ns_ingen.canvasX.me,
                                    None)),
            "y":
            lilv.lilv_node_as_float(
                lilv.lilv_world_get(world.me, block.me, ns_ingen.canvasY.me,
                                    None)),
            "enabled":
            lilv.lilv_node_as_bool(enabled) if enabled is not None else False,
            "minorVersion":
            lilv.lilv_node_as_int(minorver) if minorver else 0,
            "microVersion":
            lilv.lilv_node_as_int(microver) if microver else 0,
        })

    info['connections'] = ingenarcs
    info['plugins'] = ingenblocks

    return info