= Technical Specification =

Weed Events 1.0 beta version.

CHANGELOG
28/04/2006
Changed "owner" to "owners" for FILTER_INIT event (allow multiple
track owners for a filter)
Added optional "audio_state" leaf to FRAME event.

02/06/2006
Amended "audio_state" to "audio_seek".

22/06/2006
Remove "owners"


(C) Gabriel "Salsaman" Finch 2005 - 2006


== PLANT TYPES ==
This document describes the different plant types in the weed events system, and their mandatory
and optional leaves.


== PLANT TYPE EVENT_LIST ==

Event lists contain events which are linked as a singly or doubly
linked list. Events may be held in an event list.
Some kinds of plugins (timeline plugins) can take an event_list input
and produce an event_list output.

Event lists can also be serialised and passed between applications.

Unlike some systems where event lists (or Edit Decision Lists) are
forced to be held per-track/channel, Weed allows both this mode, and/or use of a global
event list for all tracks/channels.


 * "type" == WEED_PLANT_EVENT_LIST

'''Mandatory leaves''':[[BR]]
 
 * "fps" : WEED_SEED_DOUBLE : framerate of timeline; all events in the
   timeline MUST be quantised to this rate. An "fps" of 0 indicates
   variable framerate.

 * "first" : WEED_SEED_PLANTPTR : pointer to the first EVENT in
   the EVENT_LIST

'''Optional leaves''': [[BR]]

 * "last" : WEED_SEED_PLANTPTR : pointer to the last EVENT in
   the EVENT_LIST


== PLANT TYPE EVENT ==

 * "type" == WEED_PLANT_EVENT

'''Mandatory leaves''':[[BR]]

 * "hint"	  : WEED_SEED_INT : hint denoting the event type [see
   below, Event Hints]

 * "timecode"	  : WEED_SEED_INT64 : the timecode of the event

 * "next"	  : WEED_SEED_PLANTPTR : pointer to the next event in
   the event list. Circular references are not allowed. The "next"
   leaf of the "last" event in an event list MUST be NULL. Timecode of
   event pointed to MUST be >= this.timecode.

'''Optional leaves''': [[BR]]

 * "previous"	  : WEED_SEED_PLANTPTR : pointer to the previous event in
   the event list. Circular references are not allowed. If it exists, the "previous"
   leaf of the "first" event in an event list MUST be NULL. "previous"
   and "next" MUST form a doubly linked list, i.e there must be a symmetry. Timecode of
   event pointed to MUST be <= this.timecode.


== Order of events at one timecode ==

It is suggested that the order and number of events at each timecode
should be:

 * 0 or more effect init events
 * 0 or more parameter change events
 * 0 or 1 effect map events
 * 0 or more parameter change events
 * 1 frame event [either a blank frame or a real frame]
 * 0 or more effect deinit events
 * 0 or 1 effect map events

 * Marker events can exist anywhere in the chain.

== EVENT HINTS ==

The "hint" is a mandatory WEED_SEED_INT leaf of every event; the defined values are:

 * WEED_EVENT_HINT_FRAME
 * WEED_EVENT_HINT_FILTER_INIT
 * WEED_EVENT_HINT_FILTER_DEINIT
 * WEED_EVENT_HINT_FILTER_MAP
 * WEED_EVENT_HINT_PARAM_CHANGE
 * WEED_EVENT_HINT_MARKER

Depending on the "hint" parameter seed type additional leaves are:

=== WEED_EVENT_HINT_FRAME ===
 A FRAME event represents a stack of clip/frame pairs. Number of
 elements for "clips" and "frames" MUST be equivalent.

 * "clips" : WEED_SEED_INT : array of clips (clip number >=1)  [clip <=0 means no frame/blank frame at that position]
 * "frames" : WEED_SEED_INT : array of frames (frame number >=1) [frame <=0 means a blank frame at that position]

Optional leaves

 * "audio_seek" : WEED_SEED_DOUBLE : an array of double, giving audio
   seek times in seconds.
   A value >=0.0 means audio on, a value < 0.0 means audio off. If present, number of
   elements should match with "clips" and "frames". If not present,
   then the audio is assumed to continue playing from the prior (by timecode) "audio_seek".

   For audio without video, corresponding "frames" number can be set to
   0, with "clips" value >= 1

   There is no volume or pan setting: audio samples can be mixed using a filter (see the WEED AUDIO
   extension); this may require audio rendering.

=== WEED_EVENT_HINT_FILTER_INIT ===
    This event is used to init a filter instance.

 * "filter" : WEED_SEED_STRING :the HASHNAME of a Weed filter [See the main Weed
     spec. for a definition of the Hashname]

 * "in_count" : WEED_SEED_INT : array describing the number (count)
     of instances of each in channel template; 0 means disabled, 1 means enabled,
     >1 can be used where repeated channels are allowed : optional if
     "filter" has no in channels, otherwise number of
     elements and order must match filter "in_channel_templates"

 * "out_count" : WEED_SEED_INT : array describing the number
     (count) of instances of each out channel template; 0 means disabled, 1 means enabled,
     >1 can be used where repeated channels are allowed : optional if
     "filter" has no out channel templates, otherwise number of
     elements and order must match filter "out_channel_templates"

 * "in_tracks" : WEED_SEED_INT : array of tracks [matches subsequent
     FRAME events to effect in_channels], starts at 0 : optional if
     "filter" has no in channels

 * "out_tracks" : WEED_SEED_INT : array of tracks [matches subsequent
     FRAME events to effect out_channels], starts at 0 : optional if
     "filter" has no out channels


How this works:
in subsequent FRAME events, the "clip"/"frame" pairs ("tracks") are first
selected using "in_tracks". These are mapped onto the filter instance "in_channels" using "in_count". Once the filter has been applied,
"out_count" maps the filter "out_channel"s to "out_tracks". In other
words, "in_count" and "in_tracks" forms a tree
mapping tracks to channels, and likewise for "out_count" and "out_tracks".


Mandatory leaves for serialisation/deserialisation

 * "event_id" : WEED_SEED_VOIDPTR : for serialisation and backup of
   event lists, the "event_id" MUST be used to hold the (void *) value
   of the original event. This can later be used to reconstruct the
   original event list. Used to locate "init_event" in FILTER_MAP,
   FILTER_DEINIT and PARAM_CHANGE events after
   serialisation/deserialisation of event_list. 


=== WEED_EVENT_HINT_FILTER_DEINIT ===
    This event deinits a filter instance.

 * "init_event" : WEED_SEED_VOIDPTR : refers to a FILTER_INIT with "timecode" <= this
   event's timecode.


=== WEED_EVENT_HINT_FILTER_MAP ===
   This event type defines the order in which filters are applied to any
   subsequent FRAME events.

 * "init_events" : WEED_SEED_VOIDPTR : an array which refers to FILTER_INITs with "timecode" <= this
   event's timecode. The associated FILTER_DEINITs must have
   "timecode" >= this event's timecode.


=== WEED_EVENT_HINT_PARAM_CHANGE ===
    Parameters are assumed to be smoothly interpolated from one value
    to the next. In order to implement an instantaneous change, the
    filter should either do its own interpolation, or the old value
    should be duplicated at the timecode before the instantaneous change. 


 * "init_event" : WEED_SEED_VOIDPTR : refers to a FILTER_INIT with "timecode" <= this
   event's timecode. The referenced "init_event" must be before this
   event in the event_list. The associated FILTER_DEINIT must have
   "timecode" >= this event's timecode, and must occur after the
   PARAM_CHANGE in the event_list.

 * "index" : WEED_SEED_INT : 0 based index of in_parameter numbers
 * "value" : WEED_SEED_* : "value" of the in_parameter at "timecode"


=== WEED_EVENT_HINT_MARKER ===

This is a host specfic marker event. Leaves can vary from host to
host. Markers which are not recognised should be removed from the event_list.



== Serialising of event_lists ==

Event_lists may be serialised for transfer between applications. The
process is:

 * add "event_id" leaves to all filter_init events
 * serialise first the event_list plant, then the event plants in order of ascending timecode

The serialisation format of each plant shall be as follows:

(uint32_t) number_of_properties

then for each property:

(uint32_t) name_len | (char *) property_name | (uint32_t) atom_type |
(uint32_t) num_elems |
where name_len == strlen(property_name)
property_name is ASCII, not NUL-terminated
then for each element:

(uint32_t) byte_size | (void *) value
[strings are utf-8, not NUL terminated]

| is shown for clarity only and is not written to the output.
Byte order is little-endian.

Note: the "type" leaf should be serialised first, in order to assist
reconstruction of the deserialised plant.


== Timeline plugins ==

Timeline plugins are similar to regular Weed (pixel) plugins, except
that:

They do not have CHANNEL_TEMPLATES.

They have an extra leaf in the FILTER_CLASS, "is_timeline", seed type WEED_SEED_BOOLEAN,
which must be set to WEED_TRUE.

The host will create a FILTER_INSTANCE with no "in_channels" or
"out_channels", instead using "in_event_list" and
"out_event_list". Host should pass a pointer to its currently active event_list (or
NULL if none is active) in the "in_event_list".

Timeline plugins may either: append an event to the "in_event_list",
and return it in the "out_event_list", or create a new event_list, and
return it in the "out_event_list". Events MUST be appended in such a
way that the event "timecodes" in the event list are in ascending
order.

The host should add an extra leaf to the HOST_INFO:
"host_clip_get_frame_count", a voidptr to a host function:

int host_clip_get_frame_count(int clip_number);

If the plugin calls this function, the host should return either
number of frames in the clip, or 0. 0 should be
returned if either: the requested clip is not usable (does not exist, or, the
requested clip is not "random-access", e.g. it is a stream.)






== EVENT_HINTS ==

 * WEED_EVENT_HINT_FRAME
 * WEED_EVENT_HINT_FILTER_INIT
 * WEED_EVENT_HINT_FILTER_DEINIT
 * WEED_EVENT_HINT_FILTER_MAP
 * WEED_EVENT_HINT_PARAM_CHANGE
 * WEED_EVENT_HINT_MARKER


== FILTER_INSTANCE leaves ==

Optional leaves 

 * "is_timeline" : WEED_SEED_BOOLEAN : a setting of WEED_TRUE
   indicates that the filter is a timeline filter.

== HOST_INFO leaves ==

"host_clip_get_framecount" : WEED_SEED_VOIDPTR: pointer to function of
template int host_clip_get_frame_count(int clip_number); : host must
supply this if it wants to use timeline plugins

