Overview

Events are generated in ftrack when things happen such as a task being updated or a new version being published. Clients can listen to these events and perform an action as a result. The action could be updating another related entity based on a status change or generating folders when a new shot is created for example.

The events system in ftrack works by clients subscribing to events they are interested in and a central service routing published events accordingly.

Whilst there are several builtin events it is also possible for clients to publish their own custom events and reuse the event framework for custom purposes.

Event

An event is a standardised mapping structure that follows the form:

{
    'topic': 'unique-event-topic',
    'data': {
        # The data payload of the event.
    },
    'source': {
        # Information about the source of the event
        # (application id, current user etc).
    },
    'target': 'optional-target-expression'
}

Note
Individual Clients may implement their own event wrappers / helpers.

Event server

All events, except special synchronous ones, are routed through a central event server.

                                             /---> [subscribed client]
[client] > (published event) > [event server]
                                             \---> [subscribed client]

Connections to the event server are handled with WebSocket using socket.io.

Events are always transmitted as JSON encoded packets under the ‘ftrack.event’ namespace.

Publishing events

You can either publish standard ftrack events or leverage the event framework to publish your own events. In either case, once connected to the event server you simply need to send an event of the appropriate form to the server under the ftrack.event namespace.

Remember that all supplied information can be used by subscribers to filter events so the more accurate the information the better.

Publish synchronously

With some clients it is also possible to publish events synchronously. In this case the event would only be routed locally on that same client and never be sent to the main server. This can be useful for discovering local plugins etc.

Targeting events

In addition to subscribers filtering events to receive, it is also possible to give an event a specific target to help route it to the right subscriber.

To do this, set the target value on the event to an expression. The expression will filter against registered subscriber information.

For example, if you have many subscribers listening for a event, but only want one of those subscribers to get the event, you can target the event to the subscriber using its registered subscriber id:

{
    'topic': 'my-company.topic',
    'data': {
        # The data payload of the event.
    },
    'target': 'id=my-custom-subscriber-id'
}

Sending replies

When handling an event it is sometimes useful to be able to send information back to the source of the event. For example, ftrack.location.request-resolve would expect a resolved path to be sent back.

This is done by publishing a special reply event with the form:

{
    'topic': 'ftrack.meta.reply',
    'data': {
        # The reply data payload.
    },
    'target': 'id={source-id-of-source-event}',
    'inReplyToEvent': 'id-of-source-event'}

However, most clients will implement this functionality for you and allow you to just return a value from an event handler in order to issue a reply.

Subscribing to events

To listen to events, you register a subscription with the central event server. You do this by publishing special meta events:

{
    'topic': 'ftrack.meta.subscribe',
    'data': {
        'subscription': 'the-subscription-expression',
        'subscriber': {
            # Optional metadata about subsriber.
        }
    }
}

Likewise to unsubscribe:

{
    'topic': 'ftrack.meta.unsubscribe',
    'data': {
        'subscription': 'the-subscription-expression',
    }
}

The subscription uses the expression syntax and is used to filter against each published event to determine if the registered client should receive that event. If the subscription matches, the registered client will receive the event and would typically call a registered function, passing the event as the sole argument.

Subscriber information

When subscribing, you can also specify additional information about your subscriber under the data/subscriber key. This contextual information can be useful when routing events, particularly when targeting events. By default, most clients will automatically set basic information about the subscriber context though you are free to add your own.

Expressions

An expression is used to filter against a data structure, returning whether the structure fulfils the expression requirements. Expressions are currently used for subscriptions when subscribing to events and for targets when publishing targeted events.

The form of the expression is loosely groupings of ‘key=value’ with conjunctions to join them.

For example, a common expression for subscriptions is to filter against an event topic:

'topic=ftrack.location.component-added'

However, you can also perform more complex filtering, including accessing nested parameters:

'topic=ftrack.location.component-added and data.locationId=london'

Note
If the structure being tested does not have any value for the specified key reference then it is treated as not matching.

You can also use a single wildcard ‘*’ at the end of any value for matching multiple values. For example, the following would match all events that have a topic starting with ‘ftrack.’:

'topic=ftrack.*'

Events list

The following are standard ftrack events published by the server. Each heading refers to the ‘topic’ the event is published with. Each entry includes an example of the event (relevant information only).

ftrack.connect

Emitted by the server when it wants to perform an action in Connect (such as launching the publisher):

Event(
    topic='ftrack.connect',
    data=dict(
        action='start',
        plugin='publish',
        entity=dict(
            entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb',
            entityType='task',
        )
    )
)

ftrack.dynamic-enumerator

Emitted by server when requesting entries to populate a dynamic enumerator dropdown with:

Event(
    topic='ftrack.dynamic-enumerator',
    data=dict(
        attributeName='my_dynamic_enumerator',
        recordData=dict(
            entity=dict(
                entityType='task',
                entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb'
            ),
            changes=dict()
        ),
        query='',
        sorters=[],
        groupers=[],
        filters=[
            # Filter information.
            ...
        ]
    )
)

Expects reply data in the form:

[
    dict(
        name='Menu item name',
        value='menu_item_value'
    ),
    ...
]

ftrack.action.discover

Published by the server when it wants to get available actions:

Event(
    topic='ftrack.action.discover',
    data=dict(
        context=dict(
            selection=[
                dict(
                    entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb',
                    entityType='task',
                )
            ]
        )
    )
)

Expects reply data in the form:

dict(
    items=[
        dict(
            label='Mega Modeling',
            icon='http://mega-modeling.example.com/logo.png',
            variant='2014',
            description='Launch Mega Modeling 2014',
            actionIdentifier='my-action-callback-identifier',
            actionData=dict(
                applicationIdentifier='mega_modeling_2014'
            )
        ),
        dict(
            label='Mega Modeling',
            variant='2015',
            description='Launch Mega Modeling 2015',
            actionIdentifier='my-action-callback-identifier',
            actionData=dict(
                applicationIdentifier='mega_modeling_2015'
            )
        ),
        dict(
            label='Professional Painter',
            actionIdentifier='my-action-callback-identifier',
            actionData=dict(
                applicationIdentifier='professional_painter'
            )
        ),
        dict(
            label='Cool Compositor v2',
            actionIdentifier='my-action-callback-identifier',
            actionData=dict(
                cc_plugins=['foo', 'bar'],
                applicationIdentifier='cc_v2'
            )
        )
    ]
)

ftrack.action.launch

Published by the server when it wants to launch an action:

Event(
    topic='ftrack.action.launch',
    data=dict(
        actionIdentifier='my-action-callback-identifier',
        actionData=dict(
            applicationIdentifier='maya-2014'
        ),
        context=dict(
            selection=[
                dict(
                    entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb',
                    entityType='task',
                )
            ]
        )
    )
)

Expects reply data in the form:

dict(
    success=True,
    message='maya-2014 launched successfully.'
)

ftrack.action.trigger-user-interface

Can be published to trigger a response to a launched action remotely:

Event(
    topic='ftrack.action.trigger-user-interface',
    data=dict(
        type='message',
        success=True,
        message='A message to the user.'
    ),
    target='applicationId=ftrack.client.web and user.id="SOME-USER-ID"'
)

Different user interfaces require different data. Here is a list of attributes that may be required:

  • actionIdentifier - Required by form type to know what action to launch on submit.
  • selection - Required by form and widget types to know what entities to work with.

Have a look at action user interfaces for a list of possible user interfaces.

Note
This event is currently only supported by the ftrack web UI which is represented applicationId ftrack.client.web.

ftrack.location.component-added

Published by the Python API whenever a component is added to a location:

Event(
    topic='ftrack.location.component-added',
    data=dict(
        componentId='e2dc0524-b576-11d3-9612-080027331d74',
        locationId='07b82a97-8cf9-11e3-9383-20c9d081909b'
    )
)

ftrack.location.component-removed

Published by the Python API whenever a component is removed from a location:

Event(
    topic='ftrack.location.component-removed',
    data=dict(
        componentId='e2dc0524-b576-11d3-9612-080027331d74',
        locationId='07b82a97-8cf9-11e3-9383-20c9d081909b'
    )
)

ftrack.location.request-resolve

Published by the server when it needs to resolve a path for a component in a specific location, such as when a location is selected in the components widget:

Event(
    topic='ftrack.location.request-resolve',
    data=dict(
        locationName='london',
        componentId='zb26970c-5dc6-1132-119a-f23c9fs325eq',
        platform='Linux',
        serverUrl='http://URL-TO-SERVER:PORT'
    )
)

Expects reply data in the form:

dict(
    path='/fully/resolved/path'
)

ftrack.update

Update events are published when an entity in the system changes:

Event(
    topic='ftrack.update',
    data=dict(
        entities=[
            dict(
                action='update',
                entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb',
                entityType='task',
                keys=['statusid'],
                parents=[
                    dict(
                        entityId='5671dcb0-66de-11e1-8e6e-f23c91df25eb',
                        entityType='show'
                    )
                ]
            )
        ]
    )
)

Change information

Update events can also include additional information on what changed. This can be accessed via the ‘changes’ key on each entity in the event:

 Event(
     ...,
     data=dict(
         entities=[
             dict(
                 entityId='eb16970c-5fc6-11e2-bb9a-f23c91df25eb',
                 entityType='task',
                 changes=dict(
                     statusid=dict(
                         old='44ddd0fe-4164-11df-9218-0019bb4983d8',
                         new='44dd9fb2-4164-11df-9218-0019bb4983d8'
                     )
                 ),
                 ...
             )
         ]
     )
 )

ftrack.validate

Published when the server requests validation of user input. Currently used in the create project menu:

Event(
    topic='ftrack.validate',
    data=dict(
        # New project data.
        name='my project',
        fullname='m',
        status='active',
        startdate='2014-08-05T23:00:00.000Z',
        ...
    )
)

Expects reply data in the form:

dict(
    changes=dict(
        name=existingName.upper()
    ),
    errors=dict(
        fullname='Must be more than 3 characters.'
    )
)
Did this answer your question?