| // Copyright 2022 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| syntax = "proto3"; |
| |
| package pandora; |
| |
| import "pandora/host.proto"; |
| import "google/protobuf/empty.proto"; |
| import "google/protobuf/wrappers.proto"; |
| |
| option java_outer_classname = "A2DPProto"; |
| |
| // Service to trigger A2DP (Advanced Audio Distribution Profile) procedures. |
| // |
| // Requirements for the implementer: |
| // - Streams must not be automatically opened, even if discovered. |
| // - The `Host` service must be implemented |
| // |
| // References: |
| // - [A2DP] Bluetooth SIG, Specification of the Bluetooth System, |
| // Advanced Audio Distribution, Version 1.3 or Later |
| // - [AVDTP] Bluetooth SIG, Specification of the Bluetooth System, |
| // Audio/Video Distribution Transport Protocol, Version 1.3 or Later |
| service A2DP { |
| // Open a stream from a local **Source** endpoint to a remote **Sink** |
| // endpoint. |
| // |
| // The returned source should be in the AVDTP_OPEN state (see [AVDTP] 9.1). |
| // The rpc must block until the stream has reached this state. |
| // |
| // A cancellation of this call must result in aborting the current |
| // AVDTP procedure (see [AVDTP] 9.9). |
| rpc OpenSource(OpenSourceRequest) returns (OpenSourceResponse); |
| // Open a stream from a local **Sink** endpoint to a remote **Source** |
| // endpoint. |
| // |
| // The returned sink must be in the AVDTP_OPEN state (see [AVDTP] 9.1). |
| // The rpc must block until the stream has reached this state. |
| // |
| // A cancellation of this call must result in aborting the current |
| // AVDTP procedure (see [AVDTP] 9.9). |
| rpc OpenSink(OpenSinkRequest) returns (OpenSinkResponse); |
| // Wait for a stream from a local **Source** endpoint to |
| // a remote **Sink** endpoint to open. |
| // |
| // The returned source should be in the AVDTP_OPEN state (see [AVDTP] 9.1). |
| // The rpc must block until the stream has reached this state. |
| // |
| // If the peer has opened a source prior to this call, the server will |
| // return it. The server must return the same source only once. |
| rpc WaitSource(WaitSourceRequest) returns (WaitSourceResponse); |
| // Wait for a stream from a local **Sink** endpoint to |
| // a remote **Source** endpoint to open. |
| // |
| // The returned sink should be in the AVDTP_OPEN state (see [AVDTP] 9.1). |
| // The rpc must block until the stream has reached this state. |
| // |
| // If the peer has opened a sink prior to this call, the server will |
| // return it. The server must return the same sink only once. |
| rpc WaitSink(WaitSinkRequest) returns (WaitSinkResponse); |
| // Get if the stream is suspended |
| rpc IsSuspended(IsSuspendedRequest) returns (google.protobuf.BoolValue); |
| // Start an opened stream. |
| // |
| // The rpc must block until the stream has reached the |
| // AVDTP_STREAMING state (see [AVDTP] 9.1). |
| rpc Start(StartRequest) returns (StartResponse); |
| // Suspend a streaming stream. |
| // |
| // The rpc must block until the stream has reached the AVDTP_OPEN |
| // state (see [AVDTP] 9.1). |
| rpc Suspend(SuspendRequest) returns (SuspendResponse); |
| // Close a stream, the source or sink tokens must not be reused afterwards. |
| rpc Close(CloseRequest) returns (CloseResponse); |
| // Get the `AudioEncoding` value of a stream |
| rpc GetAudioEncoding(GetAudioEncodingRequest) |
| returns (GetAudioEncodingResponse); |
| // Playback audio by a `Source` |
| rpc PlaybackAudio(stream PlaybackAudioRequest) |
| returns (PlaybackAudioResponse); |
| // Capture audio from a `Sink` |
| rpc CaptureAudio(CaptureAudioRequest) returns (stream CaptureAudioResponse); |
| } |
| |
| // Audio encoding formats. |
| enum AudioEncoding { |
| // Interleaved stereo frames with 16-bit signed little-endian linear PCM |
| // samples at 44100Hz sample rate |
| PCM_S16_LE_44K1_STEREO = 0; |
| // Interleaved stereo frames with 16-bit signed little-endian linear PCM |
| // samples at 48000Hz sample rate |
| PCM_S16_LE_48K_STEREO = 1; |
| } |
| |
| // A Token representing a Source stream (see [A2DP] 2.2). |
| // It's acquired via an OpenSource on the A2DP service. |
| message Source { |
| // Opaque value filled by the GRPC server, must not |
| // be modified nor crafted. |
| bytes cookie = 1; |
| } |
| |
| // A Token representing a Sink stream (see [A2DP] 2.2). |
| // It's acquired via an OpenSink on the A2DP service. |
| message Sink { |
| // Opaque value filled by the GRPC server, must not |
| // be modified nor crafted. |
| bytes cookie = 1; |
| } |
| |
| // Request for the `OpenSource` method. |
| message OpenSourceRequest { |
| // The connection that will open the stream. |
| Connection connection = 1; |
| } |
| |
| // Response for the `OpenSource` method. |
| message OpenSourceResponse { |
| // Result of the `OpenSource` call. |
| oneof result { |
| // Opened stream. |
| Source source = 1; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 2; |
| } |
| } |
| |
| // Request for the `OpenSink` method. |
| message OpenSinkRequest { |
| // The connection that will open the stream. |
| Connection connection = 1; |
| } |
| |
| // Response for the `OpenSink` method. |
| message OpenSinkResponse { |
| // Result of the `OpenSink` call. |
| oneof result { |
| // Opened stream. |
| Sink sink = 1; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 2; |
| } |
| } |
| |
| // Request for the `WaitSource` method. |
| message WaitSourceRequest { |
| // The connection that is awaiting the stream. |
| Connection connection = 1; |
| } |
| |
| // Response for the `WaitSource` method. |
| message WaitSourceResponse { |
| // Result of the `WaitSource` call. |
| oneof result { |
| // Awaited stream. |
| Source source = 1; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 2; |
| } |
| } |
| |
| // Request for the `WaitSink` method. |
| message WaitSinkRequest { |
| // The connection that is awaiting the stream. |
| Connection connection = 1; |
| } |
| |
| // Response for the `WaitSink` method. |
| message WaitSinkResponse { |
| // Result of the `WaitSink` call. |
| oneof result { |
| // Awaited stream. |
| Sink sink = 1; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 2; |
| } |
| } |
| |
| // Request for the `IsSuspended` method. |
| message IsSuspendedRequest { |
| // The stream on which the function will check if it's suspended |
| oneof target { |
| Sink sink = 1; |
| Source source = 2; |
| } |
| } |
| |
| // Request for the `Start` method. |
| message StartRequest { |
| // Target of the start, either a Sink or a Source. |
| oneof target { |
| Sink sink = 1; |
| Source source = 2; |
| } |
| } |
| |
| // Response for the `Start` method. |
| message StartResponse { |
| // Result of the `Start` call. |
| oneof result { |
| // Stream successfully started. |
| google.protobuf.Empty started = 1; |
| // Stream is already in AVDTP_STREAMING state. |
| google.protobuf.Empty already_started = 2; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 3; |
| } |
| } |
| |
| // Request for the `Suspend` method. |
| message SuspendRequest { |
| // Target of the suspend, either a Sink or a Source. |
| oneof target { |
| Sink sink = 1; |
| Source source = 2; |
| } |
| } |
| |
| // Response for the `Suspend` method. |
| message SuspendResponse { |
| // Result of the `Suspend` call. |
| oneof result { |
| // Stream successfully suspended. |
| google.protobuf.Empty suspended = 1; |
| // Stream is already in AVDTP_OPEN state. |
| google.protobuf.Empty already_suspended = 2; |
| // The Connection disconnected. |
| google.protobuf.Empty disconnected = 3; |
| } |
| } |
| |
| // Request for the `Close` method. |
| message CloseRequest { |
| // Target of the close, either a Sink or a Source. |
| oneof target { |
| Sink sink = 1; |
| Source source = 2; |
| } |
| } |
| |
| // Response for the `Close` method. |
| message CloseResponse {} |
| |
| // Request for the `GetAudioEncoding` method. |
| message GetAudioEncodingRequest { |
| // The stream on which the function will read the `AudioEncoding`. |
| oneof target { |
| Sink sink = 1; |
| Source source = 2; |
| } |
| } |
| |
| // Response for the `GetAudioEncoding` method. |
| message GetAudioEncodingResponse { |
| // Audio encoding of the stream. |
| AudioEncoding encoding = 1; |
| } |
| |
| // Request for the `PlaybackAudio` method. |
| message PlaybackAudioRequest { |
| // Source that will playback audio. |
| Source source = 1; |
| // Audio data to playback. |
| // The audio data must be encoded in the specified `AudioEncoding` value |
| // obtained in response of a `GetAudioEncoding` method call. |
| bytes data = 2; |
| } |
| |
| // Response for the `PlaybackAudio` method. |
| message PlaybackAudioResponse {} |
| |
| // Request for the `CaptureAudio` method. |
| message CaptureAudioRequest { |
| // Sink that will capture audio |
| Sink sink = 1; |
| } |
| |
| // Response for the `CaptureAudio` method. |
| message CaptureAudioResponse { |
| // Captured audio data. |
| // The audio data is encoded in the specified `AudioEncoding` value |
| // obtained in response of a `GetAudioEncoding` method call. |
| bytes data = 1; |
| } |