Skip to content

ReplayingΒΆ

Screenshot Screenshot

If you have a Sen archive, you can play it back using the replayer component.

There are two ways of starting a replay. The simplest one is to do:

# load the archive and start the playback straight away
$ sen replay my_archive

# load the archive but keep the replay stopped
$ sen replay my_archive --stopped

You can see that this approach creates the replay in an independent process. While convenient, sometimes you might want to do embed replay in your own process. For example, in testing or during development.

This can be done by adding the replayer component to your configuration file. For example:

Adding the replayer to your process
  - name: replayer
    autoOpen: school_recording  # this is the path to the archive
    autoPlay: true  # start the playback right away
    group: 20

The configuration options are defined in the component's STL:

Replayer configuration options
package sen.components.replayer;

// Overall component configuration
struct Configuration
{
  bus            : string,    // bus to publish the object (local.replay by default)
  samplingPeriod : Duration,  // max sampling period for flushing the replayed data
  autoOpen       : string,    // optional archive path to auto open on start-up (empty by default)
  autoPlay       : bool       // if autoOpen is not empty, try to play it on start-up (false by default)
}

The main object of the replayer component is the Replayer object. It allows you to open multiple archives for replay. Every time you open an archive, a Replay object is created, which is the one you can use to control the playback.

The interface for these objects is this:

Replayer interface
import "stl/sen/db/basic_types.stl"

package sen.components.replayer;

// represents the replayer component and manages Replay objects.
class Replayer
{
  // if true, automatically calls play when opening a replay
  var autoPlay : bool [static];

  // opens an archive in a given path, and creates a named Replay object.
  fn open(name: string, path: string) [confirmed];

  // closes the named Replay object, if any.
  fn close(name: string) [confirmed];

  // closes all previously opened replays
  fn closeAll() [confirmed];
}

// the state in which a Replay can be
enum ReplayStatus: u8
{
  stopped, // not running, at the start of the archive
  paused,  // not running, at the position when pause was called
  playing  // performing the replay
}

// controls the replay of a given archive
class Replay
{
  // information about the archive being replayed
  var archiveInfo : sen.db.Summary [static];

  // file path to the archive
  var archivePath : string [static];

  // playback status
  var status : ReplayStatus [confirmed];

  // playback time
  var playbackTime : TimeStamp [bestEffort];

  // starts the playback from the current position
  fn play()  [confirmed];

  // hold the playback position, if playing
  fn pause() [confirmed];

  // goes to the start of the playback, erasing all objects
  fn stop() [confirmed];

  // restores the playback to the keyframe that's closest to a given time
  fn seek(time: TimeStamp) [confirmed];

  // if paused or stopped, advances the playback a given time delta
  fn advance(time: Duration);
}

The typical usage would be something like this:

sequenceDiagram
    actor You
    You->>+Replayer: open(archive)
    Replayer->>+Replay: create()
    You->>+Replay: play()

    You->>+Replay: pause()
    You->>+Replay: moveTo(time)
    You->>+Replayer: close(archive)
    You-xReplay: delete