## IpatchUnit IpatchUnit — Unit conversion system |

## Stability Level

Stable, unless otherwise indicated

## Synopsis

                        IpatchUnitInfo;
    enum                IpatchUnitFlags;
    void                (*IpatchValueTransform)             (const GValue *src,
                                                             GValue *dest);
    enum                IpatchUnitType;
    #define             IPATCH_UNIT_TYPE_FIRST_DYNAMIC_ID
    enum                IpatchUnitClassType;
    IpatchUnitInfo *    ipatch_unit_info_new                (void);
    void                ipatch_unit_info_free               (IpatchUnitInfo *info);
    guint16             ipatch_unit_register                (const IpatchUnitInfo *info);
    IpatchUnitInfo *    ipatch_unit_lookup                  (guint16 id);
    IpatchUnitInfo *    ipatch_unit_lookup_by_name          (const char *name);
    void                ipatch_unit_class_register_map      (guint16 class_type,
                                                             guint16 src_units,
                                                             guint16 dest_units);
    IpatchUnitInfo *    ipatch_unit_class_lookup_map        (guint16 class_type,
                                                             guint16 src_units);
    void                ipatch_unit_conversion_register     (guint16 src_units,
                                                             guint16 dest_units,
                                                             IpatchValueTransform func);
    IpatchValueTransform  ipatch_unit_conversion_lookup     (guint16 src_units,
                                                             guint16 dest_units,
                                                             gboolean *set);
    gboolean            ipatch_unit_convert                 (guint16 src_units,
                                                             guint16 dest_units,
                                                             const GValue *src_val,
                                                             GValue *dest_val);
    double              ipatch_unit_user_class_convert      (guint16 src_units,
                                                             const GValue *src_val);

## Description

System for registering unit types and conversion functions.

## Details

### IpatchUnitInfo

    typedef struct {
      guint16 id;			/* unit type ID */
      guint8 digits;	   	/* significant digits to display to user */
      guint8 flags;			/* IpatchUnitFlags */
      GType value_type;		/* unit value type */
      char *name;			/* name identifier (constant) */
      char *label;			/* unit label (translated) */
      char *descr;			/* unit description (translated) */
    } IpatchUnitInfo;

### enum IpatchUnitFlags

    typedef enum
    {
      IPATCH_UNIT_LOGARITHMIC = 1 << 0, /* unit is logarithmic */
      IPATCH_UNIT_USER = 1 << 1	/* a user friendly unit type */
    } IpatchUnitFlags;

### IpatchValueTransform ()

    void                (*IpatchValueTransform)             (const GValue *src,
                                                             GValue *dest);

Transform from one value to another. The `src` and `dest` values have already been initialized to specific types and the transform function should convert/process them as necessary.

`src` : | Source value to transform from
`dest` : | Destination value to transform to

### enum IpatchUnitType

    typedef enum
    {
      IPATCH_UNIT_TYPE_NONE = 0,	/* a NULL value */
      IPATCH_UNIT_TYPE_INT = 1,
      IPATCH_UNIT_TYPE_UINT = 2,
      IPATCH_UNIT_TYPE_RANGE = 3,
      IPATCH_UNIT_TYPE_DECIBELS = 4,
      IPATCH_UNIT_TYPE_PERCENT = 5,
      IPATCH_UNIT_TYPE_SEMITONES = 6,
      IPATCH_UNIT_TYPE_CENTS = 7,
      IPATCH_UNIT_TYPE_TIME_CENTS = 8,
      IPATCH_UNIT_TYPE_SAMPLE_RATE = 9,
      IPATCH_UNIT_TYPE_SAMPLES = 10,
      IPATCH_UNIT_TYPE_HERTZ = 11,
      IPATCH_UNIT_TYPE_SECONDS = 12,
      IPATCH_UNIT_TYPE_MULTIPLIER = 13,

      /* 128 - 159 reserved for IpatchUnit_DLS.h */
      IPATCH_UNIT_TYPE_DLS_GAIN = 128,
      IPATCH_UNIT_TYPE_DLS_ABS_TIME = 129,
      IPATCH_UNIT_TYPE_DLS_REL_TIME = 130,
      IPATCH_UNIT_TYPE_DLS_ABS_PITCH = 131,
      IPATCH_UNIT_TYPE_DLS_REL_PITCH = 132,
      IPATCH_UNIT_TYPE_DLS_PERCENT = 133,

      /* 160 - 169 reserved for IpatchUnit_SF2.h */
      IPATCH_UNIT_TYPE_SF2_ABS_PITCH = 160,
      IPATCH_UNIT_TYPE_SF2_OFS_PITCH = 161,
      IPATCH_UNIT_TYPE_SF2_ABS_TIME = 162,
      IPATCH_UNIT_TYPE_SF2_OFS_TIME = 163,
      IPATCH_UNIT_TYPE_CENTIBELS = 164,
      IPATCH_UNIT_TYPE_32K_SAMPLES = 165,
      IPATCH_UNIT_TYPE_TENTH_PERCENT = 166
    } IpatchUnitType;

### IPATCH_UNIT_TYPE_FIRST_DYNAMIC_ID

    #define IPATCH_UNIT_TYPE_FIRST_DYNAMIC_ID	1024

### enum IpatchUnitClassType

    typedef enum
    {
      IPATCH_UNIT_CLASS_NONE,	/* a NULL value */
      IPATCH_UNIT_CLASS_USER,   /* "user" conversion class (for humans) */
      IPATCH_UNIT_CLASS_DLS,	/* DLS (native patch type) class */
      IPATCH_UNIT_CLASS_COUNT   /* NOT A VALID CLASS - count of classes */
    } IpatchUnitClassType;

### ipatch_unit_info_new ()

    IpatchUnitInfo *    ipatch_unit_info_new                (void);

Allocate a unit info structure for registering unit types with `ipatch_unit_register()`. Using this function should minimize API changes if additional fields are added to IpatchUnitInfo. Free the returned structure with `ipatch_unit_free()` when finished registering unit types.

Returns : | The newly allocated unit info structure.

### ipatch_unit_info_free ()

    void                ipatch_unit_info_free               (IpatchUnitInfo *info);

Free a unit info structure that was created with `ipatch_unit_info_new()`.

`info` : | Unit info to free

### ipatch_unit_register ()

    guint16             ipatch_unit_register                (const IpatchUnitInfo *info);

Add a new unit type to the unit registry. Note that the `info` structure is shallow copied, so strings should be constant or guaranteed to not be freed. If the `id` field is already set (non-zero) in `info`, then it is used (should be 0 for dynamic unit types). If the `label` field of the `info` structure is `NULL` then it is set to the i18n translated string for `name`. Unit types can not be un-registered. Unit IDs of dynamic (non built-in types) should not be relied apon to always be the same between program executions.

`info` : | Unit info (shallow copied)
Returns : | New unit ID

### ipatch_unit_lookup ()

    IpatchUnitInfo *    ipatch_unit_lookup                  (guint16 id);

Looks up unit info by ID.

`id` : | Unit ID
Returns : | Unit info structure with `id` or `NULL` if not found, returned structure is internal and should not be modified or freed

### ipatch_unit_lookup_by_name ()

    IpatchUnitInfo *    ipatch_unit_lookup_by_name          (const char *name);

Looks up unit info by name.

`name` : | Unit name identifier
Returns : | Unit info structure with `name` or `NULL` if not found, returned structure is internal and should not be modified or freed

### ipatch_unit_class_register_map ()

    void                ipatch_unit_class_register_map      (guint16 class_type,
                                                             guint16 src_units,
                                                             guint16 dest_units);

Register a unit class mapping. Unit class types define domains of conversion, an example is the "user" unit class (IPATCH_UNIT_CLASS_USER) which is used to convert values to units digestable by a human. A conversion class is essentially a mapping between unit types, which can then be used to lookup conversion functions.

`class_type` : | Class type (see IpatchUnitClassType)
`src_units` : | Source unit type of mapping
`dest_units` : | Destination unit type for this map

### ipatch_unit_class_lookup_map ()

    IpatchUnitInfo *    ipatch_unit_class_lookup_map        (guint16 class_type,
                                                             guint16 src_units);

Lookup a unit class mapping (see `ipatch_unit_class_register_map()`).

`class_type` : | Class type (see IpatchUnitClassType)
`src_units` : | Source unit type of mapping to lookup
Returns : | Pointer to destination unit info structure, or `NULL` if not found.

### ipatch_unit_conversion_register ()

    void                ipatch_unit_conversion_register     (guint16 src_units,
                                                             guint16 dest_units,
                                                             IpatchValueTransform func);

Register a parameter unit conversion function.

`src_units` : | Source unit type
`dest_units` : | Destination unit type
`func` : | Conversion function handler or `NULL` for unity conversion (the value type will be converted but not the actual value, example: float -> int).

### ipatch_unit_conversion_lookup ()

    IpatchValueTransform  ipatch_unit_conversion_lookup     (guint16 src_units,
                                                             guint16 dest_units,
                                                             gboolean *set);

Lookup a conversion function by source and destination unit types.

`src_units` : | Source unit type
`dest_units` : | Destination unit type
`set` : | Location to store a boolean value indicating if the conversion is set, to differentiate between a `NULL` conversion function and an invalid conversion. Can be `NULL` in which case this parameter is ignored.
Returns : | Conversion function pointer or `NULL` if a unity conversion or no matching handlers (use `set` to determine which).

### ipatch_unit_convert ()

    gboolean            ipatch_unit_convert                 (guint16 src_units,
                                                             guint16 dest_units,
                                                             const GValue *src_val,
                                                             GValue *dest_val);

Convert a value from one unit type to another.

`src_units` : | Source unit type ID
`dest_units` : | Destination unit type ID
`src_val` : | Source value (type should be compatible with the source unit's value type)
`dest_val` : | Destination value (value should be initialized to a type that is compatible with the destination unit's value type)
Returns : | `TRUE` if value was successfully converted, `FALSE` otherwise (the only reasons for failure are invalid function parameters, no conversion function for the given unit types, or incompatible GValue types in conversion, therefore the return value can be safely ignored if the caller is sure the parameters and types are OK).

### ipatch_unit_user_class_convert ()

    double              ipatch_unit_user_class_convert      (guint16 src_units,
                                                             const GValue *src_val);

Converts a value to "user" units. User units are unit types that are adequate for human consumption. The IPATCH_UNIT_CLASS_USER map is used to lookup the corresponding user type to convert to. Not all unit types have an associated user type or the `src_units` type can itself be a user type; in either of these cases the `src_val` is converted as is (possibly converted from another value type to double).

`src_units` : | Source unit type ID
`src_val` : | Source value (type should be compatible with the source unit's value type)
Returns : | The value converted to user units.