blob: ca286a4935c584a5732ff7ebdbe779e85de6fbcf [file] [log] [blame]
Hongchan Choi7dd0b3e2019-05-13 21:19:031// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @implements {SDK.SDKModelObserver<!WebAudio.WebAudioModel>}
7 */
8WebAudio.WebAudioView = class extends UI.ThrottledWidget {
9 constructor() {
10 super(true, 1000);
11 this.element.classList.add('web-audio-drawer');
12 this.registerRequiredCSS('web_audio/webAudio.css');
13
14 // Creates the toolbar.
15 const toolbarContainer = this.contentElement.createChild(
16 'div', 'web-audio-toolbar-container vbox');
17 this._contextSelector = new WebAudio.AudioContextSelector(ls`BaseAudioContexts`);
18 const toolbar = new UI.Toolbar('web-audio-toolbar', toolbarContainer);
19 toolbar.appendToolbarItem(UI.Toolbar.createActionButtonForId('components.collect-garbage'));
20 toolbar.appendSeparator();
21 toolbar.appendToolbarItem(this._contextSelector.toolbarItem());
22
23 // Creates the detail view.
24 this._detailViewContainer = this.contentElement.createChild('div', 'vbox flex-auto');
25
26 // Creates the landing page.
27 this._landingPage = new UI.VBox();
28 this._landingPage.contentElement.classList.add('web-audio-landing-page', 'fill');
29 this._landingPage.contentElement.appendChild(UI.html`
30 <div>
31 <p>${ls`Open a page that uses Web Audio API to start monitoring.`}</p>
32 </div>
33 `);
34 this._landingPage.show(this._detailViewContainer);
35
36 // Creates the summary bar.
37 this._summaryBarContainer = this.contentElement.createChild('div', 'web-audio-summary-container');
38
39 this._contextSelector.addEventListener(WebAudio.AudioContextSelector.Events.ContextSelected, event => {
40 const context =
41 /** @type {!Protocol.WebAudio.BaseAudioContext} */ (event.data);
42 this._updateDetailView(context);
43 this.doUpdate();
44 });
45
46 SDK.targetManager.observeModels(WebAudio.WebAudioModel, this);
47 }
48
49 /**
50 * @override
51 */
52 wasShown() {
53 for (const model of SDK.targetManager.models(WebAudio.WebAudioModel))
54 this._addEventListeners(model);
55 }
56
57 /**
58 * @override
59 */
60 willHide() {
61 for (const model of SDK.targetManager.models(WebAudio.WebAudioModel))
62 this._removeEventListeners(model);
63 }
64
65 /**
66 * @override
67 * @param {!WebAudio.WebAudioModel} webAudioModel
68 */
69 modelAdded(webAudioModel) {
70 if (this.isShowing())
71 this._addEventListeners(webAudioModel);
72 }
73
74 /**
75 * @override
76 * @param {!WebAudio.WebAudioModel} webAudioModel
77 */
78 modelRemoved(webAudioModel) {
79 this._removeEventListeners(webAudioModel);
80 }
81
82 /**
83 * @override
84 * @return {!Promise<?>}
85 */
86 async doUpdate() {
87 await this._pollRealtimeData();
88 this.update();
89 }
90
91 /**
92 * @param {!WebAudio.WebAudioModel} webAudioModel
93 */
94 _addEventListeners(webAudioModel) {
95 webAudioModel.ensureEnabled();
96 webAudioModel.addEventListener(WebAudio.WebAudioModel.Events.ContextCreated, this._contextCreated, this);
97 webAudioModel.addEventListener(WebAudio.WebAudioModel.Events.ContextDestroyed, this._contextDestroyed, this);
98 webAudioModel.addEventListener(WebAudio.WebAudioModel.Events.ContextChanged, this._contextChanged, this);
99 }
100
101 /**
102 * @param {!WebAudio.WebAudioModel} webAudioModel
103 */
104 _removeEventListeners(webAudioModel) {
105 webAudioModel.removeEventListener(WebAudio.WebAudioModel.Events.ContextCreated, this._contextCreated, this);
106 webAudioModel.removeEventListener(WebAudio.WebAudioModel.Events.ContextDestroyed, this._contextDestroyed, this);
107 webAudioModel.removeEventListener(WebAudio.WebAudioModel.Events.ContextChanged, this._contextChanged, this);
108 }
109
110 /**
111 * @param {!Common.Event} event
112 */
113 _contextCreated(event) {
114 this._contextSelector.contextCreated(event);
115 }
116
117 /**
118 * @param {!Common.Event} event
119 */
120 _contextDestroyed(event) {
121 this._contextSelector.contextDestroyed(event);
122 }
123
124 /**
125 * @param {!Common.Event} event
126 */
127 _contextChanged(event) {
128 this._contextSelector.contextChanged(event);
129 }
130
131 _reset() {
132 if (this._landingPage.isShowing())
133 this._landingPage.detach();
134 this._contextSelector.reset();
135 this._detailViewContainer.removeChildren();
136 this._landingPage.show(this._detailViewContainer);
137 }
138
139 /**
140 * @param {!Protocol.WebAudio.BaseAudioContext} context
141 */
142 _updateDetailView(context) {
143 if (this._landingPage.isShowing())
144 this._landingPage.detach();
145 const detailBuilder = new WebAudio.ContextDetailBuilder(context);
146 this._detailViewContainer.removeChildren();
147 this._detailViewContainer.appendChild(detailBuilder.getFragment());
148 }
149
150 /**
151 * @param {!Protocol.WebAudio.ContextId} contextId
152 * @param {!Protocol.WebAudio.ContextRealtimeData} contextRealtimeData
153 */
154 _updateSummaryBar(contextId, contextRealtimeData) {
155 const summaryBuilder =
156 new WebAudio.AudioContextSummaryBuilder(contextId, contextRealtimeData);
157 this._summaryBarContainer.removeChildren();
158 this._summaryBarContainer.appendChild(summaryBuilder.getFragment());
159 }
160
161 _clearSummaryBar() {
162 this._summaryBarContainer.removeChildren();
163 }
164
165 async _pollRealtimeData() {
166 const context = this._contextSelector.selectedContext();
167 if (!context) {
168 this._clearSummaryBar();
169 return;
170 }
171
172 for (const model of SDK.targetManager.models(WebAudio.WebAudioModel)) {
173 // Display summary only for real-time context.
174 if (context.contextType === 'realtime') {
175 const realtimeData = await model.requestRealtimeData(context.contextId);
176 if (realtimeData && realtimeData.currentTime && realtimeData.renderCapacity)
177 this._updateSummaryBar(context.contextId, realtimeData);
178 } else {
179 this._clearSummaryBar();
180 }
181 }
182 }
183};