// Copyright 2018 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.

library fuchsia.media.playback;

using fuchsia.media;
using zx;

/// Manages sources on behalf of a Player.
protocol SourceManager {
    /// Creates a source that reads from a file.
    CreateFileSource(zx.handle:CHANNEL file_channel,
                     request<Source> source_request);

    /// Creates a source that reads from a `SeekingReader`.
    CreateReaderSource(SeekingReader seeking_reader,
                       request<Source> source_request);

    /// Creates a source that allows the client to provide independent elementary
    /// streams to the player. duration_ns, can_pause, can_seek and metadata are
    /// all included in the SourceStatus and, when the `ElementarySource` is used by
    /// the player, in the `PlayerStatus` as well. `can_pause` and `can_seek`, when
    /// false, constrain the capabilities of the player.
    CreateElementarySource(zx.duration duration_ns, bool can_pause, bool can_seek,
                           fuchsia.media.Metadata? metadata,
                           request<ElementarySource> source_request);

    /// Sets the source for this player to use. If source is null, the player
    /// becomes idle.
    SetSource(Source? source);

    /// Transitions to the specified source when playback of the current source
    /// reaches transition_pts. The new source starts playback at start_pts. If
    /// a transition is already pending, it will be discarded in favor of the new
    /// transition.
    TransitionToSource(Source source, int64 transition_pts,
                       int64 start_pts);

    /// Cancels a pending transition, returning the source. If no transition is
    /// pending, the request channel is closed.
    CancelSourceTransition(request<Source> returned_source_request);
};

/// A source of content that may be used by a player.
protocol Source {
    // Provides current status immediately after binding and whenever status
    // changes thereafter.
    -> OnStatusChanged(SourceStatus source_status);
};

/// `Source` variant for providing elementary streams directly to the player.
protocol ElementarySource {
    compose Source;

    /// Adds an elementary stream. The elementary stream can be removed by
    /// closing the `SimpleStreamSink`. `ticks_per_second_numerator` and
    /// `ticks_per_second_denominator` indicate the units that will be used for
    /// `Streampacket` timestamp values. For nanoseconds units, for example,
    /// `ticks_per_second_numerator` should be 1000000000 and
    /// `ticks_per_second_denominator` should be 1. To use units of frames for
    /// 48k audio, `ticks_per_second_numerator` should be 48000 and
    /// `ticks_per_second_denominator` should be 1.
    //
    // SimpleStreamSink methods not currently implemented:
    //     DiscardAllPackets
    //     DiscardAllPacketsNoReply
    AddStream(
        fuchsia.media.StreamType type,
        uint32 ticks_per_second_numerator,
        uint32 ticks_per_second_denominator,
        request<fuchsia.media.SimpleStreamSink> sink_request);

    /// Adds a new binding to this `ElementarySource`. By using this method,
    /// the client can obtain an additional channel through which to communicate
    /// to this `ElementarySource` even after a channel is consumed by a call to
    /// `SourceManager.SetSource`.
    // IMPLEMENTATION NOTE:
    // This method is implemented, however a limitation in the current
    // implementation requires that the StreamSource handle passed to
    // SourceManager.SetSource be created from the connection established by the
    // original CreateStreamSource call. That is, a connection established
    // using AddBinding cannot be passed to SourceManager.SetSource.
    // TODO(dalesat): Remove this limitation.
    AddBinding(request<ElementarySource> source_request);
};

/// Source status information.
struct SourceStatus {
    /// Duration of the content.
    zx.duration duration;

    /// Whether the source can pause.
    bool can_pause;

    /// Whether the source can seek.
    bool can_seek;

    /// Whether the source has an audio stream.
    bool has_audio;

    /// Whether the source has a video stream.
    bool has_video;

    /// Indicates whether the source is ready. A true value signals that the
    /// content has been probed and there are no known problems with it.
    bool ready;

    /// Describes the media.
    fuchsia.media.Metadata? metadata;

    /// Indicates a problem preventing intended operation. A null value
    /// indicates that the source is functioning as intended.
    Problem? problem;
};
