// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// A library of protocols for routing media between devices.
///
/// This library is based on "targets", which are devices or groups of devices
/// which can render media sessions. See `fuchsia.media.sessions2` for media
/// session details.
///
/// Through the `Discovery` protocol, clients can discover what media targets
/// are available on the network, and select them to render media sessions.
library fuchsia.media.target;

using fuchsia.media;
using fuchsia.media.audio;
using fuchsia.media.sessions2;

/// A unique id for a target.
alias Id = uint64;

/// A user-visible name for a target to display in user interface or read
/// in voice interfaces.
alias DisplayName = string:200;

/// A protocol for discovering media targets.
[Discoverable]
protocol Discovery {
    compose Group;
    compose Selector;

    /// Watches for bindings of media sessions to targets.
    ///
    /// A media session is rendered on the target to which it is bound.
    ///
    /// Bindings are returned as deltas between the watch calls, leave a
    /// request hanging to get the latest updates.
    WatchSessionBindings() -> (SessionBindingsWatchEvent event);

    /// Connects to a target by id. Drops the given channel if no such
    /// target exists.
    ConnectToTarget(Id target_id, request<Target> target_request);
};

/// A binding between a session and a target, indicating the media session
/// is rendered on the target.
struct SessionBinding {
    fuchsia.media.sessions2.SessionId session_id;
    Id target_id;
};

table SessionBindingsWatchEvent {
    /// A list of active session bindings added or updated in the network
    /// at any point in time.
    1: vector<SessionBinding>:MAX updated;

    /// A list of session bindings that are removed in the network since
    /// notified.
    2: vector<SessionBinding>:MAX removed;
};

/// A target is a device or group of devices on which media can be rendered,
/// such as a speaker which renders audio.
protocol Target {
    compose GroupEditor;
    compose Group;
    compose VolumeControl;
};

struct TargetChange {
    Id new_target_id;
};

/// A protocol for adding and removing members of a group target.
protocol GroupEditor {
    /// Adds a target to this group target.
    ///
    /// If the added target is a group of devices, all the devices in that group
    /// are added to this group. A group itself cannot be a member of a group.
    ///
    /// Returns the id of the new target if a new group was created to fulfill this
    /// request.
    AddTarget(Id target_id) -> (TargetChange? target_change) error Error;

    /// Removes a target from this group. Returns the id of the new target
    /// if a new group was created to fulfill this request.
    RemoveTarget(Id target_id) -> (TargetChange? target_change) error Error;
};

/// A protocol for watching the members of a group.
protocol Group {
    /// Watches for changes to the set of registered targets. Leave a request
    /// hanging to get replies when changes occur. New clients will be caught
    /// up with the state of the world.
    ///
    /// Targets are returned as deltas between the watch calls.
    WatchTargets() -> (TargetsWatchEvent targets_watch_event);
};

table TargetsWatchEvent {
    /// Targets added or updated on the network at any point in time.
    1: vector<Description>:MAX updated;

    /// Targets that are removed since last notified.
    2: vector<Id>:MAX removed;
};

/// A protocol to control the volume of target.
protocol VolumeControl {
    /// Binds to the target's volume control. If this target is a group,
    /// all member volumes are influenced. These settings persist
    /// for the lifetime of the target.
    BindVolumeControl(request<fuchsia.media.audio.VolumeControl> volume_control_request);

    /// Binds to the target's volume control as a member of the given group.
    /// The request channel is dropped if the target is not a member of the group.
    ///
    /// This volume control influences the volume of this target only when it is
    /// participating as a member of the group. This is used to adjust the balance
    /// of volume among members of a group. These settings persist for the lifetime
    /// of the target
    BindMemberVolumeControl(
        Id group,
        request<fuchsia.media.audio.VolumeControl> volume_control_request);
};

/// A description of a target.
table Description {
    /// Identifies the target.
    1: Id target_id;
    /// Enumerates of the interoperability features the device supports.
    2: CapabilityFlags capability_flags;
    3: DisplayName display_name;
    4: fuchsia.media.Metadata metadata;
};

/// Capabilities of the target.
bits CapabilityFlags : uint64 {
    /// Indicates the target can receive a transfer of a
    /// media session from another target.
    TRANSFER_TO = 0x01;
    /// Indicates the target can transfer a media session
    /// to another target.
    TRANSFER_FROM = 0x02;
    /// Indicates the target can participate in rendering
    /// media with other devices.
    MULTI_TARGET_PLAYBACK = 0x04;
    /// Indicates the target can render video.
    VIDEO = 0x08;
};

/// A protocol for selecting a media target. Commands on this protocol can
/// change the target on which a media session is rendered.
protocol Selector {
    /// Renders the media session specified by `session_id` on the target
    /// specified by `target_id`.
    BindTarget(
        fuchsia.media.sessions2.SessionId session_id,
        Id target_id) -> () error Error;

    /// Renders the media session specified by `session_id` on the set of
    /// targets specified by `target_ids`.
    ///
    /// This may create a new group target which contains all the specified
    /// targets as members, if one does not exist. The group target may be
    /// temporary, only existing for the lifetime of playback, and not
    /// discoverable through `Discovery`.
    BindGroupTarget(
        fuchsia.media.sessions2.SessionId session_id,
        vector<Id>:100 target_ids
        ) -> (Id target_id) error Error;
};

enum Error {
    NOT_A_GROUP = 0;
    UNKNOWN_ON_DOMAIN = 1;
    CANNOT_BE_GROUPED = 2;
    NOT_MEMBER_OF_GROUP = 3;
    TRANSFER_FROM_TARGET_UNSUPPORTED = 4;
    TRANSFER_TO_TARGET_UNSUPPORTED = 5;
    MULTI_TARGET_PLAYBACK_UNSUPPORTED = 6;
};
