// Medea's Control API gRPC schema.

syntax = "proto3";

package api;

import "google/protobuf/duration.proto";

// Media server's Control API service.
service ControlApi {
  // Creates new Element with a given ID.
  //
  // Not idempotent. Errors if an Element with the same ID already exists.
  rpc Create (CreateRequest) returns (CreateResponse);

  // Removes Element by its ID.
  // Allows referring multiple Elements on the last two levels.
  //
  // Idempotent. If no Elements with such IDs exist, then succeeds.
  rpc Delete (IdRequest) returns (Response);

  // Returns Element by its ID.
  // Allows referring multiple Elements.
  // If no ID specified, returns all Elements declared.
  rpc Get (IdRequest) returns (GetResponse);

  // Applies the given spec to Element by its ID.
  //
  // Idempotent. If no Element with such ID exists, then it will be created,
  // otherwise it will be reconfigured. Elements that exist, but are not
  // specified in the provided spec will be removed.
  rpc Apply(ApplyRequest) returns (CreateResponse);
}

// Request of creating new Element with in element with a given FID (full ID).
message CreateRequest {
  // FID (full ID) of the Element in which the provided Element will be created.
  string parent_fid = 1;
  // Spec of the created Element.
  oneof el {
    Member member = 2;
    Room room = 3;
    WebRtcPlayEndpoint webrtc_play = 4;
    WebRtcPublishEndpoint webrtc_pub = 5;
  }
}

// Request with many FIDs (full IDs) of Elements.
message IdRequest {
  // List of Elements FIDs.
  repeated string fid = 1;
}

// Request of applying a spec to Element with the given FID (full ID).
message ApplyRequest {
  // FID (full ID) of the Element to apply the given spec to.
  string parent_fid = 1;
  // Spec of the Element to be applied.
  oneof el {
    Member member = 2;
    Room room = 3;
    WebRtcPlayEndpoint webrtc_play = 4;
    WebRtcPublishEndpoint webrtc_pub = 5;
  }
}

// Response which doesn't return anything on successful result,
// but is fallible with an Error.
//
// If operation fails then an Error will be returned.
// The response is considered successful only if it does not contain Error.
message Response {
  // Error of the Response.
  Error error = 1;
}

// Response of Create RPC method.
//
// If operation fails then an Error will be returned.
// The response is considered successful only if it does not contain Error.
message CreateResponse {
  // Hashmap with IDs (key) and URIs (value) of Elements, which should be used
  // by clients to connect to a media server via Client API.
  //
  // Returned only if CreateResponse is successful.
  map<string, string> sid = 1;
  // Error of the CreateResponse.
  Error error = 2;
}

// Response of Get RPC method.
//
// If operation fails then an Error will be returned.
// The response is considered successful only if it does not contain Error.
message GetResponse {
  // Hashmap with IDs (key) and specs (value) of the requested Elements.
  //
  // Returned only if GetResponse is successful.
  map<string, Element> elements = 1;
  // Error of the GetResponse.
  Error error = 2;
}

// Error of failed request.
//
// If the Error is not returned then request is considered as successful.
message Error {
  // Concrete unique code of the Error.
  uint32 code = 1;
  // Human-readable text description of the Error.
  string text = 2;
  // Link to online documentation of the Error.
  //
  // Optional field.
  string doc = 3;
  // Full ID of Element that the Error is related to.
  // Some Errors are not related to any Element and in such case
  // this field is empty.
  //
  // Optional field.
  string element = 4;
}

// Media element which can be used in a media pipeline.
message Element {
  oneof el {
    Member member = 1;
    Room room = 2;
    WebRtcPlayEndpoint webrtc_play = 3;
    WebRtcPublishEndpoint webrtc_pub = 4;
  }
}

// Media element which represents a single space where multiple Members can
// interact with each other.
message Room {
  // ID of this Room.
  string id = 1;
  // Pipeline of this Room.
  map<string, Room.Element> pipeline = 2;

  // Elements which Room's pipeline can contain.
  message Element {
    oneof el {
      Member member = 1;
      WebRtcPlayEndpoint webrtc_play = 2;
      WebRtcPublishEndpoint webrtc_pub = 3;
    }
  }
}

// Media element which represents a client authorized to participate
// in a some bigger media pipeline.
message Member {
  // ID of this Member.
  string id = 1;
  // Callback which fires when the Member establishes persistent connection
  // with a media server via Client API.
  string on_join = 2;
  // Callback which fires when the Member finishes persistent connection
  // with a media server via Client API.
  string on_leave = 3;
  // Credentials of the Member to authorize via Client API with.
  //
  // Plain and hashed credentials are supported. If no credentials provided,
  // then random plain string will be generated. If no authentication is
  // required then empty plain string can be used.
  //
  // Hashed variant only supports Argon2 hash at the moment.
  // Member sid won't contain token if hashed credentials are used, so token
  // query parameter should be appended manually.
  oneof credentials {
    // Argon2 hash of credentials.
    string hash = 4;
    // Plain text credentials.
    string plain = 5;
  }
  // Timeout of receiving heartbeat messages from the Member via Client API.
  // Once reached, the Member is considered being idle.
  google.protobuf.Duration idle_timeout = 6;
  // Timeout of the Member reconnecting via Client API.
  // Once reached, the Member is considered disconnected.
  google.protobuf.Duration reconnect_timeout = 7;
  // Interval of sending pings from a media server to the Member via Client API.
  google.protobuf.Duration ping_interval = 8;
  // Pipeline of this Member.
  map<string, Member.Element> pipeline = 9;

  // Elements which Member's pipeline can contain.
  message Element {
    oneof el {
      WebRtcPlayEndpoint webrtc_play = 1;
      WebRtcPublishEndpoint webrtc_pub = 2;
    }
  }
}

// Media element which is able to receive media data from a client via WebRTC
// (allows to publish media data).
message WebRtcPublishEndpoint {
  // ID of this WebRtcPublishEndpoint.
  string id = 1;
  // P2P mode for this element.
  P2P p2p = 2;
  // Callback which fires when a client starts publishing media data.
  string on_start = 3;
  // Callback which fires when a client stops publishing media data.
  string on_stop = 4;
  // Option to relay all media through a TURN server forcibly.
  bool force_relay = 5;
  // Settings for the audio media type of this element.
  AudioSettings audio_settings = 6;
  // Settings for the video media type of this element.
  VideoSettings video_settings = 7;

  // Audio media type settings of WebRtcPublishEndpoint.
  message AudioSettings {
    // Policy to publish audio media type with.
    PublishPolicy publish_policy = 1;
  }

  // Video media type settings of WebRtcPublishEndpoint.
  message VideoSettings {
    // Policy to publish video media type with.
    PublishPolicy publish_policy = 1;
  }

  // Policy of how the video or audio media type can be published in
  // WebRtcPublishEndpoint.
  enum PublishPolicy {
    // Media type MAY be published.
    //
    // Media server will try to initialize publishing, but won't produce any
    // errors if user application fails to (or chooses not to) acquire a
    // required media track. Media server will approve user requests to stop and
    // to restart publishing the specified media type.
    OPTIONAL = 0;
    // Media type MUST be published.
    //
    // Media server will try to initialize publishing, and if a required media
    // track couldn't be acquired, then an error will be thrown. Media server
    // will deny all requests to stop publishing.
    REQUIRED = 1;
    // Media type MUST not be published.
    //
    // Media server will not try to initialize publishing.
    DISABLED = 2;
  }

  // P2P mode of WebRTC interaction.
  enum P2P {
    // Always send media data through a media server.
    NEVER = 0;
    // Send media data peer-to-peer directly if it's possible,
    // otherwise through a media server.
    IF_POSSIBLE = 1;
    // Send media data peer-to-peer only without a media server.
    ALWAYS = 2;
  }
}

// Media element which is able to play media data for a client via WebRTC.
message WebRtcPlayEndpoint {
  // ID of this WebRtcPlayEndpoint.
  string id = 1;
  // The source to get media data from.
  string src = 2;
  // Callback which fires when a client starts playing media data
  // from the source.
  string on_start = 3;
  // Callback which fires when a client stops playing media data
  // from the source.
  string on_stop = 4;
  // Option to relay all media through a TURN server forcibly.
  bool force_relay = 5;
}
