Skip to content

Tags: IDMIL/libmapper

Tags

2.1

Version 2.1

s

1.2

Version 1.2

v1.2a

Update thread handling for SWIG/Python bindings.

1.1

Version 1.1

1.0

Changes from 0.4 to 1.0

-----------------------

Released Jan 4, 2016.

This is release includes many API changes, improvements, and new
features since 0.4. They are summarized very briefly here:

The data structures in libmapper have been reconceived to increase consistency
and clarity. Some data structures have been merged and/or renamed:

* `mapper_device` + `mapper_db_device` ––> `mapper_device`
* `mapper_signal` + `mapper_db_signal` ––> `mapper_signal`
* `mapper_link` + `mapper_db_link` ––> `mapper_link`
* `mapper_connection` + `mapper_db_connection` ––> `mapper_map`
* `mapper_admin` ––> `mapper_network`
* `mapper_monitor` ––> (removed)
* `mapper_db` ––> `mapper_database`

This means that the database now represents remote devices and signals using the
same data structures that are used for local devices and signals. Property
getter and setter functions for these structures are the same whether the entity
is local or remote. The property getter `<object>_is_local()` can be used to
retrieve whether the data structure represents a local resource.

The `mapper_map` structure is now a "top-level" object, and is used for
creating, modifying, and destroying mapping connections. Changes to a map (and
to other structures that represent non-local resources) must be explicitly
synchronized with the network using the `_push()` function, e.g.:

    mapper_map map = mapper_map_new(num_srcs, outsigs, insig);
    mapper_map_set_expression(map, "y=x+2");
    mapper_map_push(map);

Or in C++:

    mapper::Map map(outsig, insig);
    map.set_expression("y=x+2");
    map.push();

Or in Python:

    map = mapper.map(outsig, insig)
    map.expression = "y=x+2"
    map.push()

Or in Java:

    mapper.Map map = new mapper.Map(outsig, insig);
    map.setExpression("y=x+2");
    map.push();

In all these cases the arguments for the map constructor are no longer the
*names* of the signals in question, but are **signal objects**: `mapper_signal`
in C, `mapper::Signal` in C++, etc. These could be local signals or signals
retrieved from the database.

There is also a new data structure called `mapper_slot` for representing map
endpoints (see below under **convergent mapping**). This means that for properties
such as minimum, maximum, and boundary behaviours it is the *slot* property that
needs to be set.

The names of many functions have been changed to make them consistent with the
names of the data structures they concern, e.g. `mdev_poll()` has been renamed
to `mapper_device_poll()`.

Previous versions of libmapper contained many duplicate functions for accessing
e.g. signals belonging to a device: one for retrieving them from a `mapper_device`
and another for retrieving them from the database. In version 0.5 all object
queries have been unified, and children of objects (e.g. signals, maps) are
retrieved by querying their parent. For example, all devices can be retrieved
from the database like this:

    mapper_device *devs = mapper_database_devices(db);
    while (devs) {
        printf("retrieved device '%s'\n", mapper_device_name(*devs));
        devs = mapper_device_query_next(devs);
    }

The old way of retrieving the output signals belonging to a particular device
was to call:

    mapper_db_signal *sigs = mapper_db_get_outputs_by_device_name(db, name);

and the new way:

    mapper_device dev = mapper_database_device_by_name(db, name);
    mapper_signal *sigs = mapper_device_signals(dev, MAPPER_DIR_OUTGOING);

Queries can be combined using `union`, `intersection`, or `difference`
operators, making it easy to e.g. find maps with a specific source and
destination device without requiring a dedicated function to do so:

    mapper_map *src, *dst, *combo;

    src = mapper_device_maps(src_dev, MAPPER_DIR_OUTGOING);
    dst = mapper_device_maps(dst_dev, MAPPER_DIR_INCOMING);
    combo = mapper_map_query_intersection(src, dst);

    while (combo) {
        mapper_map_pp(*combo);
        maps = mapper_map_query_next(combo);
    }

The data structures `mapper_device`, `mapper_signal`, and `mapper_map` can also
now be queried by arbitrary property, making it quite easy to build arbitrary
queries:

    // retrieve all maps with the property 'foo' where its value is < 10
    int value = 10;
    mapper_map *maps = mapper_database_maps_by_property(db, "foo", 1, 'i',
                                                        &value,
                                                        MAPPER_OP_LESS_THAN);

*Convergent* (or *many-to-one*) mapping refers to scenarios in which multiple
source signals are connected to the same destination signal. Prior to 0.5,
libmapper would allow a naïve implementation of convergent mapping: multiple
sources could be connected to a given destination, but their values would
overwrite each other at each source update. Starting with version 0.5, three
other methods for convergent mapping are also available:

* _Updating specific vector elements or element ranges_. By using the vector
indexing functionality mentioned above, parts of vector destinations can be
updated by different sources; vectors updates are now null-padded so elements
not addressed in the expression property will not be overwritten
* _Destination value reference_. References to past values of the destination in
the expression string (e.g. `y=y{-1}+x`) now refer to the _actual value_ of the
destination signal rather than the output of the expression. If the past
behaviour is desired, a user-defined variable can be used to cache the
expression output (e.g. `foo=foo+x; y=foo`). Note that if the destination value
is referenced in the expression string, libmapper will automatically move signal
processing to the destination device.
* _Multi-source maps_. Lastly, maps can now be created with multiple source
signals, and expressions can specify arbitrary combinations of the source values.
To support this functionality, the endpoints of maps are now represented using the
`mapper_slot` data structure; each map has a single destination slot and at
least one source slot. Several properties that used to belong to connections
have been moved to the map slots:

  * `map->range` ––> `slot->minimum` and `slot->maximum`
  * `map->bound_max` ––> `slot->bound_max`
  * `map->bound_min` ––> `slot->bound_min`
  * `map->send_as_instance` ––> `slot->use_as_instance`

Calibration used to be specified using the connection mode `MO_CALIBRATE`. It is
specified using the slot property `calibrating`.

If all source slots belong to the same device, signal processing will be handled
by the source device by default, otherwise the destination will handle
evaluation of the expression. This can be controlled by setting the
`process_location` property of a map to either `MAPPER_LOC_SOURCE` or
`MAPPER_LOC_DESTINATION`. If a map has sources from different devices, or if the
map expression references the value of the destination (`y{-n}`) the processing
location will be set to `MAPPER_LOC_DESTINATION`.

The `mode` property of maps has changed a bit:

* `MO_BYPASS` has been removed since it didn't really describe what was going
on - although the expression evaluator was not being called the updates were
still undergoing type-coercion and vector padding/truncation. There is a new
mode called `MAPPER_MODE_RAW` that is used internally only when setting up
convergent maps.
* `MO_REVERSE` has been removed and replaced with directed maps; if a map from
a sink signal to a source signal is desired it is simply set up that way, e.g.
`mapper_map_new(sink_sig, source_sig)`.
* `MO_CALIBRATE` has been removed and replaced with the `mapper_slot` property
`calibrating`.
* `MO_EXPRESSION` has been renamed `MAPPER_MODE_EXPRESSION`
* `MO_LINEAR` has been renamed `MAPPER_MODE_LINEAR`

There have also been a number of internal improvements that have minimal effect
on the API but improve memory-management and add functionality

* *Memory management:* Memory is now recovered from dropped connections, e.g.
when a peer device crashes or doesn't disconnect properly.
* *Links.* Devices now create network links automatically as needed.
* *Protocol changes:* In addition to the database subscription changes, some
other updates have been made to the libmapper protocol:
  * null-padding of incomplete vector updates
  * references to maps in the protocol now have an explicit direction, e.g.
`/map ,sss "/srcdev.1/srcsig" "->" "/dstdev.1/dstsig"`. This means that maps can
now be defined between **any** set of signals, including `output->input`
(a "normal" connection), `input->output` (was a "reverse-mode" connection in
previous versions), `output->output`, and `input->input`
  * instance updates are explicitly tagged with their index, i.e. `@instance 2`
* *Efficient polling:* select() is now used internally to wait on servers,
resulting in less wasted processing and more responsive performance.

* *C++.* Headers and tests for C++ have been added to the distribution, and
are mostly complete.
* *Python.* The SWIG/Python bindings have been largely rewritten to support
API changes in libmapper and for consistency with other object-oriented
libmapper bindings (C++, Java).
* *Java.* The jni bindings have been largely rewritten to support API changes
in libmapper and to improve consistency.

0.4

Version 0.4

0.3

Release 0.3 of libmapper.

0.2

Release 0.2 of libmapper.

0.1

Release 0.1 of libmapper.