blob: 7321324a954cd3b6d046d4925ad4133a6bb45a37 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @implements {Protocol.WebAudioDispatcher}
*/
export class WebAudioModel extends SDK.SDKModel {
/**
* @param {!SDK.Target} target
*/
constructor(target) {
super(target);
this._enabled = false;
this._agent = target.webAudioAgent();
target.registerWebAudioDispatcher(this);
// TODO(crbug.com/963510): Some OfflineAudioContexts are not uninitialized
// properly because LifeCycleObserver::ContextDestroyed() is not fired for
// unknown reasons. This creates inconsistency in AudioGraphTracer
// and AudioContextSelector in DevTools.
//
// To resolve this inconsistency, we flush the leftover from the previous
// frame when the current page is loaded. This call can be omitted when the
// bug is fixed.
SDK.targetManager.addModelListener(
SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this._flushContexts, this);
}
_flushContexts() {
this.dispatchEventToListeners(Events.ModelReset);
}
/**
* @override
* @return {!Promise}
*/
suspendModel() {
this.dispatchEventToListeners(Events.ModelSuspend);
return this._agent.disable();
}
/**
* @override
* @return {!Promise}
*/
resumeModel() {
if (!this._enabled) {
return Promise.resolve();
}
return this._agent.enable();
}
ensureEnabled() {
if (this._enabled) {
return;
}
this._agent.enable();
this._enabled = true;
}
/**
* @param {!Protocol.WebAudio.BaseAudioContext} context
* @override
*/
contextCreated(context) {
this.dispatchEventToListeners(Events.ContextCreated, context);
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @override
*/
contextWillBeDestroyed(contextId) {
this.dispatchEventToListeners(Events.ContextDestroyed, contextId);
}
/**
* @param {!Protocol.WebAudio.BaseAudioContext} context
* @override
*/
contextChanged(context) {
this.dispatchEventToListeners(Events.ContextChanged, context);
}
/**
* @param {!Protocol.WebAudio.AudioListener} listener
* @override
*/
audioListenerCreated(listener) {
this.dispatchEventToListeners(Events.AudioListenerCreated, listener);
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} listenerId
* @override
*/
audioListenerWillBeDestroyed(contextId, listenerId) {
this.dispatchEventToListeners(Events.AudioListenerWillBeDestroyed, {contextId, listenerId});
}
/**
* @param {!Protocol.WebAudio.AudioNode} node
* @override
*/
audioNodeCreated(node) {
this.dispatchEventToListeners(Events.AudioNodeCreated, node);
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} nodeId
* @override
*/
audioNodeWillBeDestroyed(contextId, nodeId) {
this.dispatchEventToListeners(Events.AudioNodeWillBeDestroyed, {contextId, nodeId});
}
/**
* @param {!Protocol.WebAudio.AudioParam} param
* @override
*/
audioParamCreated(param) {
this.dispatchEventToListeners(Events.AudioParamCreated, param);
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} nodeId
* @param {!Protocol.WebAudio.GraphObjectId} paramId
* @override
*/
audioParamWillBeDestroyed(contextId, nodeId, paramId) {
this.dispatchEventToListeners(Events.AudioParamWillBeDestroyed, {contextId, paramId});
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} sourceId
* @param {!Protocol.WebAudio.GraphObjectId} destinationId
* @param {number=} sourceOutputIndex
* @param {number=} destinationInputIndex
* @override
*/
nodesConnected(contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex) {
this.dispatchEventToListeners(
Events.NodesConnected, {contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex});
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} sourceId
* @param {?Protocol.WebAudio.GraphObjectId=} destinationId
* @param {number=} sourceOutputIndex
* @param {number=} destinationInputIndex
* @override
*/
nodesDisconnected(contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex) {
this.dispatchEventToListeners(
Events.NodesDisconnected, {contextId, sourceId, destinationId, sourceOutputIndex, destinationInputIndex});
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} sourceId
* @param {!Protocol.WebAudio.GraphObjectId} destinationId
* @param {number=} sourceOutputIndex
* @override
*/
nodeParamConnected(contextId, sourceId, destinationId, sourceOutputIndex) {
this.dispatchEventToListeners(Events.NodeParamConnected, {
contextId,
sourceId,
destinationId,
sourceOutputIndex,
});
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @param {!Protocol.WebAudio.GraphObjectId} sourceId
* @param {!Protocol.WebAudio.GraphObjectId} destinationId
* @param {number=} sourceOutputIndex
* @override
*/
nodeParamDisconnected(contextId, sourceId, destinationId, sourceOutputIndex) {
this.dispatchEventToListeners(Events.NodeParamDisconnected, {
contextId,
sourceId,
destinationId,
sourceOutputIndex,
});
}
/**
* @param {!Protocol.WebAudio.GraphObjectId} contextId
* @return {!Promise<?Protocol.WebAudio.ContextRealtimeData>}
*/
async requestRealtimeData(contextId) {
return await this._agent.getRealtimeData(contextId);
}
}
SDK.SDKModel.register(WebAudioModel, SDK.Target.Capability.DOM, false);
/** @enum {symbol} */
export const Events = {
ContextCreated: Symbol('ContextCreated'),
ContextDestroyed: Symbol('ContextDestroyed'),
ContextChanged: Symbol('ContextChanged'),
ModelReset: Symbol('ModelReset'),
ModelSuspend: Symbol('ModelSuspend'),
AudioListenerCreated: Symbol('AudioListenerCreated'),
AudioListenerWillBeDestroyed: Symbol('AudioListenerWillBeDestroyed'),
AudioNodeCreated: Symbol('AudioNodeCreated'),
AudioNodeWillBeDestroyed: Symbol('AudioNodeWillBeDestroyed'),
AudioParamCreated: Symbol('AudioParamCreated'),
AudioParamWillBeDestroyed: Symbol('AudioParamWillBeDestroyed'),
NodesConnected: Symbol('NodesConnected'),
NodesDisconnected: Symbol('NodesDisconnected'),
NodeParamConnected: Symbol('NodeParamConnected'),
NodeParamDisconnected: Symbol('NodeParamDisconnected'),
};
/* Legacy exported object */
self.WebAudio = self.WebAudio || {};
/* Legacy exported object */
WebAudio = WebAudio || {};
/**
* @constructor
*/
WebAudio.WebAudioModel = WebAudioModel;
/** @enum {symbol} */
WebAudio.WebAudioModel.Events = Events;