• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15syntax = "proto3";
16
17package pandora;
18
19import "pandora/host.proto";
20import "google/protobuf/empty.proto";
21import "google/protobuf/wrappers.proto";
22
23option java_outer_classname = "A2DPProto";
24
25// Service to trigger A2DP (Advanced Audio Distribution Profile) procedures.
26//
27// Requirements for the implementer:
28// - Streams must not be automatically opened, even if discovered.
29// - The `Host` service must be implemented
30//
31// References:
32// - [A2DP] Bluetooth SIG, Specification of the Bluetooth System,
33//    Advanced Audio Distribution, Version 1.3 or Later
34// - [AVDTP] Bluetooth SIG, Specification of the Bluetooth System,
35//    Audio/Video Distribution Transport Protocol, Version 1.3 or Later
36service A2DP {
37  // Open a stream from a local **Source** endpoint to a remote **Sink**
38  // endpoint.
39  //
40  // The returned source should be in the AVDTP_OPEN state (see [AVDTP] 9.1).
41  // The rpc must block until the stream has reached this state.
42  //
43  // A cancellation of this call must result in aborting the current
44  // AVDTP procedure (see [AVDTP] 9.9).
45  rpc OpenSource(OpenSourceRequest) returns (OpenSourceResponse);
46  // Open a stream from a local **Sink** endpoint to a remote **Source**
47  // endpoint.
48  //
49  // The returned sink must be in the AVDTP_OPEN state (see [AVDTP] 9.1).
50  // The rpc must block until the stream has reached this state.
51  //
52  // A cancellation of this call must result in aborting the current
53  // AVDTP procedure (see [AVDTP] 9.9).
54  rpc OpenSink(OpenSinkRequest) returns (OpenSinkResponse);
55  // Wait for a stream from a local **Source** endpoint to
56  // a remote **Sink** endpoint to open.
57  //
58  // The returned source should be in the AVDTP_OPEN state (see [AVDTP] 9.1).
59  // The rpc must block until the stream has reached this state.
60  //
61  // If the peer has opened a source prior to this call, the server will
62  // return it. The server must return the same source only once.
63  rpc WaitSource(WaitSourceRequest) returns (WaitSourceResponse);
64  // Wait for a stream from a local **Sink** endpoint to
65  // a remote **Source** endpoint to open.
66  //
67  // The returned sink should be in the AVDTP_OPEN state (see [AVDTP] 9.1).
68  // The rpc must block until the stream has reached this state.
69  //
70  // If the peer has opened a sink prior to this call, the server will
71  // return it. The server must return the same sink only once.
72  rpc WaitSink(WaitSinkRequest) returns (WaitSinkResponse);
73  // Get if the stream is suspended
74  rpc IsSuspended(IsSuspendedRequest) returns (google.protobuf.BoolValue);
75  // Start an opened stream.
76  //
77  // The rpc must block until the stream has reached the
78  // AVDTP_STREAMING state (see [AVDTP] 9.1).
79  rpc Start(StartRequest) returns (StartResponse);
80  // Suspend a streaming stream.
81  //
82  // The rpc must block until the stream has reached the AVDTP_OPEN
83  // state (see [AVDTP] 9.1).
84  rpc Suspend(SuspendRequest) returns (SuspendResponse);
85  // Close a stream, the source or sink tokens must not be reused afterwards.
86  rpc Close(CloseRequest) returns (CloseResponse);
87  // Get the `AudioEncoding` value of a stream
88  rpc GetAudioEncoding(GetAudioEncodingRequest)
89      returns (GetAudioEncodingResponse);
90  // Playback audio by a `Source`
91  rpc PlaybackAudio(stream PlaybackAudioRequest)
92      returns (PlaybackAudioResponse);
93  // Capture audio from a `Sink`
94  rpc CaptureAudio(CaptureAudioRequest) returns (stream CaptureAudioResponse);
95}
96
97// Audio encoding formats.
98enum AudioEncoding {
99  // Interleaved stereo frames with 16-bit signed little-endian linear PCM
100  // samples at 44100Hz sample rate
101  PCM_S16_LE_44K1_STEREO = 0;
102  // Interleaved stereo frames with 16-bit signed little-endian linear PCM
103  // samples at 48000Hz sample rate
104  PCM_S16_LE_48K_STEREO = 1;
105}
106
107// A Token representing a Source stream (see [A2DP] 2.2).
108// It's acquired via an OpenSource on the A2DP service.
109message Source {
110  // Opaque value filled by the GRPC server, must not
111  // be modified nor crafted.
112  bytes cookie = 1;
113}
114
115// A Token representing a Sink stream (see [A2DP] 2.2).
116// It's acquired via an OpenSink on the A2DP service.
117message Sink {
118  // Opaque value filled by the GRPC server, must not
119  // be modified nor crafted.
120  bytes cookie = 1;
121}
122
123// Request for the `OpenSource` method.
124message OpenSourceRequest {
125  // The connection that will open the stream.
126  Connection connection = 1;
127}
128
129// Response for the `OpenSource` method.
130message OpenSourceResponse {
131  // Result of the `OpenSource` call.
132  oneof result {
133    // Opened stream.
134    Source source = 1;
135    // The Connection disconnected.
136    google.protobuf.Empty disconnected = 2;
137  }
138}
139
140// Request for the `OpenSink` method.
141message OpenSinkRequest {
142  // The connection that will open the stream.
143  Connection connection = 1;
144}
145
146// Response for the `OpenSink` method.
147message OpenSinkResponse {
148  // Result of the `OpenSink` call.
149  oneof result {
150    // Opened stream.
151    Sink sink = 1;
152    // The Connection disconnected.
153    google.protobuf.Empty disconnected = 2;
154  }
155}
156
157// Request for the `WaitSource` method.
158message WaitSourceRequest {
159  // The connection that is awaiting the stream.
160  Connection connection = 1;
161}
162
163// Response for the `WaitSource` method.
164message WaitSourceResponse {
165  // Result of the `WaitSource` call.
166  oneof result {
167    // Awaited stream.
168    Source source = 1;
169    // The Connection disconnected.
170    google.protobuf.Empty disconnected = 2;
171  }
172}
173
174// Request for the `WaitSink` method.
175message WaitSinkRequest {
176  // The connection that is awaiting the stream.
177  Connection connection = 1;
178}
179
180// Response for the `WaitSink` method.
181message WaitSinkResponse {
182  // Result of the `WaitSink` call.
183  oneof result {
184    // Awaited stream.
185    Sink sink = 1;
186    // The Connection disconnected.
187    google.protobuf.Empty disconnected = 2;
188  }
189}
190
191// Request for the `IsSuspended` method.
192message IsSuspendedRequest {
193  // The stream on which the function will check if it's suspended
194  oneof target {
195    Sink sink = 1;
196    Source source = 2;
197  }
198}
199
200// Request for the `Start` method.
201message StartRequest {
202  // Target of the start, either a Sink or a Source.
203  oneof target {
204    Sink sink = 1;
205    Source source = 2;
206  }
207}
208
209// Response for the `Start` method.
210message StartResponse {
211  // Result of the `Start` call.
212  oneof result {
213    // Stream successfully started.
214    google.protobuf.Empty started = 1;
215    // Stream is already in AVDTP_STREAMING state.
216    google.protobuf.Empty already_started = 2;
217    // The Connection disconnected.
218    google.protobuf.Empty disconnected = 3;
219  }
220}
221
222// Request for the `Suspend` method.
223message SuspendRequest {
224  // Target of the suspend, either a Sink or a Source.
225  oneof target {
226    Sink sink = 1;
227    Source source = 2;
228  }
229}
230
231// Response for the `Suspend` method.
232message SuspendResponse {
233  // Result of the `Suspend` call.
234  oneof result {
235    // Stream successfully suspended.
236    google.protobuf.Empty suspended = 1;
237    // Stream is already in AVDTP_OPEN state.
238    google.protobuf.Empty already_suspended = 2;
239    // The Connection disconnected.
240    google.protobuf.Empty disconnected = 3;
241  }
242}
243
244// Request for the `Close` method.
245message CloseRequest {
246  // Target of the close, either a Sink or a Source.
247  oneof target {
248    Sink sink = 1;
249    Source source = 2;
250  }
251}
252
253// Response for the `Close` method.
254message CloseResponse {}
255
256// Request for the `GetAudioEncoding` method.
257message GetAudioEncodingRequest {
258  // The stream on which the function will read the `AudioEncoding`.
259  oneof target {
260    Sink sink = 1;
261    Source source = 2;
262  }
263}
264
265// Response for the `GetAudioEncoding` method.
266message GetAudioEncodingResponse {
267  // Audio encoding of the stream.
268  AudioEncoding encoding = 1;
269}
270
271// Request for the `PlaybackAudio` method.
272message PlaybackAudioRequest {
273  // Source that will playback audio.
274  Source source = 1;
275  // Audio data to playback.
276  // The audio data must be encoded in the specified `AudioEncoding` value
277  // obtained in response of a `GetAudioEncoding` method call.
278  bytes data = 2;
279}
280
281// Response for the `PlaybackAudio` method.
282message PlaybackAudioResponse {}
283
284// Request for the `CaptureAudio` method.
285message CaptureAudioRequest {
286  // Sink that will capture audio
287  Sink sink = 1;
288}
289
290// Response for the `CaptureAudio` method.
291message CaptureAudioResponse {
292  // Captured audio data.
293  // The audio data is encoded in the specified `AudioEncoding` value
294  // obtained in response of a `GetAudioEncoding` method call.
295  bytes data = 1;
296}
297