Projection - OpenSlides/OpenSlides GitHub Wiki

General structure

A meeting has multiple projectors that can project some models within this meeting. There is at least one projector in the meeting and one reference projector. This projector cannot be deleted and gives a "hint" for the current list of speakers where to look for the "current" item.

Projectors

Projectors have many fields, that plainly can be updated. The scale and scroll fields have a dedicated action to control them. The projector/used_as_reference_projector_meeting_id can only be updated by updating the meeting/reference_projector_id.

Projectors can be the default projectors for something to project. The relations meeting/default_projector_*_ids provide the default projectors for each type of default (look in the models.yml to see a list of all possible fields). It is also only settable by updating the meeting.

All projector management actions:

projector.create

Payload

{
    // Required
    name: string,
    meeting_id: Id,

    // Optional
    is_internal: boolean,
    width: number,
    aspect_ratio_numerator: number,
    aspect_ratio_denominator: number,
    color: string,
    background_color: string,
    header_background_color: string,
    header_font_color: string,
    header_h1_color: string,
    chyron_background_color: string,
    chyron_font_color: string,
    show_header_footer: boolean,
    show_title: boolean,
    show_logo: boolean,
    show_clock: boolean,

    used_as_reference_projector_meeting_id: Id,
    used_as_default_projector_for_agenda_item_list_in_meeting_id: Id,
    used_as_default_projector_for_topic_in_meeting_id: Id,
    used_as_default_projector_for_list_of_speakers_in_meeting_id: Id,
    used_as_default_projector_for_current_list_of_speakers_in_meeting_id: Id,
    used_as_default_projector_for_motion_in_meeting_id: Id,
    used_as_default_projector_for_amendment_in_meeting_id: Id,
    used_as_default_projector_for_motion_block_in_meeting_id: Id,
    used_as_default_projector_for_assignment_in_meeting_id: Id,
    used_as_default_projector_for_mediafile_in_meeting_id: Id,
    used_as_default_projector_for_message_in_meeting_id: Id,
    used_as_default_projector_for_countdown_in_meeting_id: Id,
    used_as_default_projector_for_assignment_poll_in_meeting_id: Id,
    used_as_default_projector_for_motion_poll_in_meeting_id: Id,
    used_as_default_projector_for_poll_in_meeting_id: Id,
}
  • All color strings must match ^#[0-9a-f]{6}$
  • is_internal may not be set if the projector/used_as_reference_projector_meeting_id relation is set.

projector.update

Payload

{
    // Required
    id: Id,

    // Optional
    name: string,
    is_internal: boolean,
    width: number,
    aspect_ratio_numerator: number,
    aspect_ratio_denominator: number,
    color: string,
    background_color: string,
    header_background_color: string,
    header_font_color: string,
    header_h1_color: string,
    chyron_background_color: string,
    chyron_font_color: string,
    show_header_footer: boolean,
    show_title: boolean,
    show_logo: boolean,
    show_clock: boolean,

    used_as_default_projector_for_agenda_item_list_in_meeting_id: Id,
    used_as_default_projector_for_topic_in_meeting_id: Id,
    used_as_default_projector_for_list_of_speakers_in_meeting_id: Id,
    used_as_default_projector_for_current_list_of_speakers_in_meeting_id: Id,
    used_as_default_projector_for_motion_in_meeting_id: Id,
    used_as_default_projector_for_amendment_in_meeting_id: Id,
    used_as_default_projector_for_motion_block_in_meeting_id: Id,
    used_as_default_projector_for_assignment_in_meeting_id: Id,
    used_as_default_projector_for_mediafile_in_meeting_id: Id,
    used_as_default_projector_for_message_in_meeting_id: Id,
    used_as_default_projector_for_countdown_in_meeting_id: Id,
    used_as_default_projector_for_assignment_poll_in_meeting_id: Id,
    used_as_default_projector_for_motion_poll_in_meeting_id: Id,
    used_as_default_projector_for_poll_in_meeting_id: Id,
}
  • All color strings must match ^#[0-9a-f]{6}$
  • is_internal may not be set, if the projector/used_as_reference_projector_meeting_id is set.

projector.delete

Payload

{
    id: Id,
}

This must be prevented if the projector/used_as_reference_projector_meeting_id relation is set. If the projector was the default projector for some collections (used_as_default_projector_for_*_in_meeting_id), the reverse relations must change to the meeting/reference_projector_id.

projector.control_view

Payload:

{
    // required
    id: Id,
    field: "scale" | "scroll",
    direction: "up" | "down" | "reset",
    // optional
    step: number,
}

Calling this action modifies the given field. Directions:

  • up: Add step (1 as default) to the field
  • down: Subtract step (1 as default) from the field
  • reset: Set the field to 0

If the given step is less than 1 it is set to 1.

Projections

A projection is a kind of M2M model connecting projectors and the projected objects. The projected object is referenced through projection/content_object_id. The projector is referenced through projection/current_projector_id. (Note: for preview_projector_id and history_projector_id see Preview and history). The projection holds optional options in a client-defined JSON object. A projection can be stable or unstable (boolean field stable). This allows for these projections to stay projected, something else is projected on the projector. Each projection has a weight so they can be ordered and a type. The type is an optional string the client can provide. It allows for distinguishing between two projections of with the same content_object_id

A projector can have multiple current projections, but there can be at most only one unstable projection.

Two projections are called equal if their content_object_id, stable and type are equal.

Project something (projector.project)

Payload:

{
    // required
    ids: Id[], // you can project on multiple projectors
    meeting_id: Id, // to distinguish between meetings for user as content_object
    content_object_id: Fqid,
    // optional
    options: JSON,
    stable: boolean,
    type: string,
}

First, it is checked that the content object can be projected. It must be a valid object in regards to the projection/content_object_id relation and from the same meeting. Also all given projectors must be from the same meeting.

Next, check all projectors of this meeting, if there is are current equal projections. Unset all these projector/current_projection_ids relations and append only the projections with stable=False to the history of the corresponding projector.

Additionally, if the stable flag is false:

  • move all unstable projections on the given projectors to the history.
  • set the projector scroll to 0 for all given projectors.

Now create a projection for each projector to project on. In our example two projections, one for projector 1 and one for projector 2, must be created. These projections are added to the corresponding projector/current_element_ids.

Note that the ids in the payload can be an empty array. This is intentional and used to unproject a certain content object.

Toggle projections (projector.toggle)

Payload:

{
    // required
    ids: Id[], // you can toggle on multiple projectors
    meeting_id: Id,
    content_object_id: Fqid,
    // optional
    options: JSON,
    stable: boolean,
    type: string,
}

In contrast to projector.project this action does not affect all projectors of the meeting but only the given ones. This is used to control a slide on a single projector without modifying other projectors.

All projectors and content objects must belong to the same meeting given with meeting_id in the payload. For each projector:

  • There is a current equal projection: Remove the equal projection. If it was not stable, put it into the history.
  • There is not current equal projection: Create a new current projection. It it is unstable, move all unstable projections to the history and set the projector scroll to 0.

Change projection options (projection.update_options)

Without modifying the history or other projectors or projections, one has the ability to update projection/options. This is useful when e.g. projecting a pdf (mediafile). In the options the current page is stored, so when changing the page, just the options has to be updated. Payload:

{
    // required
    id: Id,
    options: JSON,
}

Unproject without history (projection.delete)

Payload

{
    // required
    id: Id, // projection id
}

It is only allowed to do so for projections with the current_projector_id or preview_projector_id relation set.

Preview and history

A projector has two relations projector/preview_projection_ids and projector/history_projection_ids holding the preview and history. Referenced projections are only allowed to be unstable. Both relations are ordered through projection/weight:

  • Preview: The projection with the lowest weight is the next one to project. New projections in the preview get max(weight)+1.
  • History: The projection with the lowest weight is the oldest. New projections in the history get max(weight)+1.

It might be possible, that multiple projections must be moved into the preview or history. They must get different weights, but the order is not given, so the backend is free to choose an order.

Invariant: A projection must always have exactly one of preview_projector_id, current_projector_id and history_projector_id set.

To navigate projections between preview, current and history, there are two actions:

projector.next

Payload:

{
    // required
    id: Id, // projector id
}

If there is no projection in the projector/preview_projection_ids do nothing. Move all unstable projections in projector/current_projection_ids to the history. Add the lowest-weight projection in projector/preview_projection_ids to projector/current_projection_ids and remove it from the preview.

projector.previous

Payload:

{
    // required
    id: Id, // projector id
}

If there is no projection in the projector/history_projection_ids do nothing. Move all unstable projections in projector/current_projection_ids to the front of the preview, so they get min(weight)-1 weight. Add the highest-weight projection in projector/history_projection_ids to projector/current_projection_ids and remove it from the history.

Manage the preview

The preview is a bit more managed than the history:

projector.add_to_preview

This action has the same payload as projector.project, but it adds the implied projection to the end of each projector's preview. Each projection gets the weight of max(weight)+1 per projector preview.

projector.project_preview

Payload:

{
    // required
    id: Id, // projection id
}

The given projection must be in a preview of a projector. Move all unstable projections in projector/current_projection_ids to the history. Add the given projection to projector/current_projection_ids and remove it from the preview.

projector.sort_preview

Payload:

{
    // required
    id: Id, // projector id
    projection_ids: Id[],
}

All projections from the projectors projector/preview_projection_ids must be given. The projection/weight must be changed accordingly.

Permissions

For all actions projector.can_manage is required.

⚠️ **GitHub.com Fallback** ⚠️