Skip to content

Commit

Permalink
WebIDL changes for AudioContext.setSinkId()
Browse files Browse the repository at this point in the history
This implements: WebAudio/web-audio-api#2498
sinkId and setSinkId are added to support selecting an audio output
device. setSinkId() will take in sinkId as a DOMString and return a
pending promise. This CL adds IDL / attribute / method for setSinkId and
will be gated behind AudioContextSetSinkId/test.

Related CL: 3838685
Reference document: go/webaudio-setsinkid-api

Bug: 1216187
Change-Id: I001743125bbf0dce8104c23d34f10d33fb562f48
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3862684
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Alvin Ji <alvinji@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1042229}
NOKEYCHECK=True
GitOrigin-RevId: 7aa2e143bc33131d4fd9080da0ba97e6c8e6a345
  • Loading branch information
Alvin Ji authored and Copybara-Service committed Sep 1, 2022
1 parent 757e2ca commit ed0955c
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 0 deletions.
2 changes: 2 additions & 0 deletions blink/public/mojom/use_counter/metrics/web_feature.mojom
Expand Up @@ -3667,6 +3667,8 @@ enum WebFeature {
kV8TurboFanOsrCompileStarted = 4346,
kV8Document_HasRedemptionRecord_Method = 4347,
kDeferredShaping2ReshapedByLastResort = 4348,
kAudioContextSinkId = 4349,
kAudioContextSetSinkId = 4350,

// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
Expand Down
1 change: 1 addition & 0 deletions blink/renderer/core/events/event_type_names.json5
Expand Up @@ -276,6 +276,7 @@
"shippingoptionchange",
"show",
"signalingstatechange",
"sinkchange",
"slotchange",
"soundend",
"soundstart",
Expand Down
30 changes: 30 additions & 0 deletions blink/renderer/modules/webaudio/audio_context.cc
Expand Up @@ -883,4 +883,34 @@ double AudioContext::GetOutputLatencyQuantizingFactor() const {
: kOutputLatencyQuatizingFactor;
}

String AudioContext::sinkId() const {
DCHECK(IsMainThread());

return sink_id_;
}

ScriptPromise AudioContext::setSinkId(ScriptState* script_state,
const String& sink_id,
ExceptionState& exception_state) {
DCHECK(IsMainThread());

ScriptPromise promise = ScriptPromise();

if (ContextState() == kClosed) {
exception_state.ThrowDOMException(
DOMExceptionCode::kInvalidStateError,
"Cannot invoke setSinkId() on a closed AudioContext.");
return promise;
}

exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"setSinkId is not supported.");

return promise;
}

void AudioContext::NotifySetSinkIdIsDone() {
DispatchEvent(*Event::Create(event_type_names::kSinkchange));
}

} // namespace blink
12 changes: 12 additions & 0 deletions blink/renderer/modules/webaudio/audio_context.h
Expand Up @@ -48,6 +48,9 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext,
const WebAudioLatencyHint&,
absl::optional<float> sample_rate);
~AudioContext() override;

DEFINE_ATTRIBUTE_EVENT_LISTENER(sinkchange, kSinkchange)

void Trace(Visitor*) const override;

// For ContextLifeCycleObserver
Expand Down Expand Up @@ -95,6 +98,12 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext,
// mojom::blink::PermissionObserver
void OnPermissionStatusChange(mojom::blink::PermissionStatus) override;

String sinkId() const;

ScriptPromise setSinkId(ScriptState*, const String&, ExceptionState&);

void NotifySetSinkIdIsDone();

protected:
void Uninitialize() final;

Expand Down Expand Up @@ -228,6 +237,9 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext,
HeapMojoRemote<mojom::blink::PermissionService> permission_service_;
HeapMojoReceiver<mojom::blink::PermissionObserver, AudioContext>
permission_receiver_;

// Initializes `sink_id_` with "" for the default audio output device.
String sink_id_ = "";
};

} // namespace blink
Expand Down
3 changes: 3 additions & 0 deletions blink/renderer/modules/webaudio/audio_context.idl
Expand Up @@ -52,4 +52,7 @@ enum AudioContextLatencyCategory {
[RaisesException, MeasureAs=AudioContextCreateMediaStreamSource] MediaStreamAudioSourceNode createMediaStreamSource(MediaStream mediaStream);
[RaisesException, MeasureAs=AudioContextCreateMediaStreamDestination] MediaStreamAudioDestinationNode createMediaStreamDestination();

[RuntimeEnabled=AudioContextSetSinkId, MeasureAs=AudioContextSinkId] readonly attribute DOMString sinkId;
[RuntimeEnabled=AudioContextSetSinkId, MeasureAs=AudioContextSetSinkId, RaisesException, CallWith=ScriptState] Promise<void> setSinkId(DOMString sinkId);
[RuntimeEnabled=AudioContextSetSinkId] attribute EventHandler onsinkchange;
};
6 changes: 6 additions & 0 deletions blink/renderer/platform/runtime_enabled_features.json5
Expand Up @@ -200,6 +200,12 @@
origin_trial_allows_third_party: true,
status: "experimental",
},
// The runtime flag for AudioContext.setSinkID().
// See: https://github.com/WebAudio/web-audio-api/pull/2498
{
name: "AudioContextSetSinkId",
status: "test",
},
{
name: "AudioOutputDevices",
// Android does not yet support switching of audio output devices
Expand Down
Expand Up @@ -273,15 +273,19 @@ interface AudioBufferSourceNode : AudioScheduledSourceNode
interface AudioContext : BaseAudioContext
attribute @@toStringTag
getter baseLatency
getter onsinkchange
getter outputLatency
getter sinkId
method close
method constructor
method createMediaElementSource
method createMediaStreamDestination
method createMediaStreamSource
method getOutputTimestamp
method resume
method setSinkId
method suspend
setter onsinkchange
interface AudioData
attribute @@toStringTag
getter duration
Expand Down

0 comments on commit ed0955c

Please sign in to comment.