Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: chrome/browser/resources/file_manager/audio_player/elements/audio_player.js

Issue 247123002: Move Files.app files to ui/file_manager (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix the test failure on non-chromeos Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 'use strict';
6
7 Polymer('audio-player', {
8 /**
9 * Child Elements
10 */
11 audioController: null,
12 audioElement: null,
13 trackList: null,
14
15 // Attributes of the element (lower characters only).
16 // These values must be used only to data binding and shouldn't be assigned
17 // any value nowhere except in the handler.
18 playing: false,
19 currenttrackurl: '',
20 playcount: 0,
21
22 /**
23 * Model object of the Audio Player.
24 * @type {AudioPlayerModel}
25 */
26 model: null,
27
28 /**
29 * Initializes an element. This method is called automatically when the
30 * element is ready.
31 */
32 ready: function() {
33 this.audioController = this.$.audioController;
34 this.audioElement = this.$.audio;
35 this.trackList = this.$.trackList;
36
37 this.addEventListener('keydown', this.onKeyDown_.bind(this));
38
39 this.audioElement.volume = 0; // Temporary initial volume.
40 this.audioElement.addEventListener('ended', this.onAudioEnded.bind(this));
41 this.audioElement.addEventListener('error', this.onAudioError.bind(this));
42
43 var onAudioStatusUpdatedBound = this.onAudioStatusUpdate_.bind(this);
44 this.audioElement.addEventListener('timeupdate', onAudioStatusUpdatedBound);
45 this.audioElement.addEventListener('ended', onAudioStatusUpdatedBound);
46 this.audioElement.addEventListener('play', onAudioStatusUpdatedBound);
47 this.audioElement.addEventListener('pause', onAudioStatusUpdatedBound);
48 this.audioElement.addEventListener('suspend', onAudioStatusUpdatedBound);
49 this.audioElement.addEventListener('abort', onAudioStatusUpdatedBound);
50 this.audioElement.addEventListener('error', onAudioStatusUpdatedBound);
51 this.audioElement.addEventListener('emptied', onAudioStatusUpdatedBound);
52 this.audioElement.addEventListener('stalled', onAudioStatusUpdatedBound);
53 },
54
55 /**
56 * Registers handlers for changing of external variables
57 */
58 observe: {
59 'trackList.currentTrackIndex': 'onCurrentTrackIndexChanged',
60 'audioController.playing': 'onControllerPlayingChanged',
61 'audioController.time': 'onControllerTimeChanged',
62 'model.volume': 'onVolumeChanged',
63 },
64
65 /**
66 * Invoked when trackList.currentTrackIndex is changed.
67 * @param {number} oldValue old value.
68 * @param {number} newValue new value.
69 */
70 onCurrentTrackIndexChanged: function(oldValue, newValue) {
71 var currentTrackUrl = '';
72
73 if (oldValue != newValue) {
74 var currentTrack = this.trackList.getCurrentTrack();
75 if (currentTrack && currentTrack.url != this.audioElement.src) {
76 this.audioElement.src = currentTrack.url;
77 currentTrackUrl = this.audioElement.src;
78 if (this.audioController.playing)
79 this.audioElement.play();
80 }
81 }
82
83 // The attributes may be being watched, so we change it at the last.
84 this.currenttrackurl = currentTrackUrl;
85 },
86
87 /**
88 * Invoked when audioController.playing is changed.
89 * @param {boolean} oldValue old value.
90 * @param {boolean} newValue new value.
91 */
92 onControllerPlayingChanged: function(oldValue, newValue) {
93 this.playing = newValue;
94
95 if (newValue) {
96 if (!this.audioElement.src) {
97 var currentTrack = this.trackList.getCurrentTrack();
98 if (currentTrack && currentTrack.url != this.audioElement.src) {
99 this.audioElement.src = currentTrack.url;
100 }
101 }
102
103 if (this.audioElement.src) {
104 this.currenttrackurl = this.audioElement.src;
105 this.audioElement.play();
106 return;
107 }
108 }
109
110 // When the new status is "stopped".
111 this.cancelAutoAdvance_();
112 this.audioElement.pause();
113 this.currenttrackurl = '';
114 this.lastAudioUpdateTime_ = null;
115 },
116
117 /**
118 * Invoked when audioController.volume is changed.
119 * @param {number} oldValue old value.
120 * @param {number} newValue new value.
121 */
122 onVolumeChanged: function(oldValue, newValue) {
123 this.audioElement.volume = newValue / 100;
124 },
125
126 /**
127 * Invoked when the model changed.
128 * @param {AudioPlayerModel} oldValue Old Value.
129 * @param {AudioPlayerModel} newValue New Value.
130 */
131 modelChanged: function(oldValue, newValue) {
132 this.trackList.model = newValue;
133 this.audioController.model = newValue;
134
135 // Invoke the handler manually.
136 this.onVolumeChanged(0, newValue.volume);
137 },
138
139 /**
140 * Invoked when audioController.time is changed.
141 * @param {number} oldValue old time (in ms).
142 * @param {number} newValue new time (in ms).
143 */
144 onControllerTimeChanged: function(oldValue, newValue) {
145 // Ignores updates from the audio element.
146 if (this.lastAudioUpdateTime_ === newValue)
147 return;
148
149 if (this.audioElement.readyState !== 0)
150 this.audioElement.currentTime = this.audioController.time / 1000;
151 },
152
153 /**
154 * Invoked when the next button in the controller is clicked.
155 * This handler is registered in the 'on-click' attribute of the element.
156 */
157 onControllerNextClicked: function() {
158 this.advance_(true /* forward */, true /* repeat */);
159 },
160
161 /**
162 * Invoked when the previous button in the controller is clicked.
163 * This handler is registered in the 'on-click' attribute of the element.
164 */
165 onControllerPreviousClicked: function() {
166 this.advance_(false /* forward */, true /* repeat */);
167 },
168
169 /**
170 * Invoked when the playback in the audio element is ended.
171 * This handler is registered in this.ready().
172 */
173 onAudioEnded: function() {
174 this.playcount++;
175 this.advance_(true /* forward */, this.model.repeat);
176 },
177
178 /**
179 * Invoked when the playback in the audio element gets error.
180 * This handler is registered in this.ready().
181 */
182 onAudioError: function() {
183 this.scheduleAutoAdvance_(true /* forward */, this.model.repeat);
184 },
185
186 /**
187 * Invoked when the time of playback in the audio element is updated.
188 * This handler is registered in this.ready().
189 * @private
190 */
191 onAudioStatusUpdate_: function() {
192 this.audioController.time =
193 (this.lastAudioUpdateTime_ = this.audioElement.currentTime * 1000);
194 this.audioController.duration = this.audioElement.duration * 1000;
195 this.audioController.playing = !this.audioElement.paused;
196 },
197
198 /**
199 * Invoked when receiving a request to replay the current music from the track
200 * list element.
201 */
202 onReplayCurrentTrack: function() {
203 // Changes the current time back to the beggining, regardless of the current
204 // status (playing or paused).
205 this.audioElement.currentTime = 0;
206 this.audioController.time = 0;
207 },
208
209 /**
210 * Goes to the previous or the next track.
211 * @param {boolean} forward True if next, false if previous.
212 * @param {boolean} repeat True if repeat-mode is enabled. False otherwise.
213 * @private
214 */
215 advance_: function(forward, repeat) {
216 this.cancelAutoAdvance_();
217
218 var nextTrackIndex = this.trackList.getNextTrackIndex(forward, true);
219 var isNextTrackAvailable =
220 (this.trackList.getNextTrackIndex(forward, repeat) !== -1);
221
222 this.audioController.playing = isNextTrackAvailable;
223
224 // If there is only a single file in the list, 'currentTrackInde' is not
225 // changed and the handler is not invoked. Instead, plays here.
226 // TODO(yoshiki): clean up the code around here.
227 if (isNextTrackAvailable &&
228 this.trackList.currentTrackIndex == nextTrackIndex) {
229 this.audioElement.play();
230 }
231
232 this.trackList.currentTrackIndex = nextTrackIndex;
233
234 Platform.performMicrotaskCheckpoint();
235 },
236
237 /**
238 * Timeout ID of auto advance. Used internally in scheduleAutoAdvance_() and
239 * cancelAutoAdvance_().
240 * @type {number}
241 * @private
242 */
243 autoAdvanceTimer_: null,
244
245 /**
246 * Schedules automatic advance to the next track after a timeout.
247 * @param {boolean} forward True if next, false if previous.
248 * @param {boolean} repeat True if repeat-mode is enabled. False otherwise.
249 * @private
250 */
251 scheduleAutoAdvance_: function(forward, repeat) {
252 this.cancelAutoAdvance_();
253 this.autoAdvanceTimer_ = setTimeout(
254 function() {
255 this.autoAdvanceTimer_ = null;
256 // We are advancing only if the next track is not known to be invalid.
257 // This prevents an endless auto-advancing in the case when all tracks
258 // are invalid (we will only visit each track once).
259 this.advance_(forward, repeat, true /* only if valid */);
260 }.bind(this),
261 3000);
262 },
263
264 /**
265 * Cancels the scheduled auto advance.
266 * @private
267 */
268 cancelAutoAdvance_: function() {
269 if (this.autoAdvanceTimer_) {
270 clearTimeout(this.autoAdvanceTimer_);
271 this.autoAdvanceTimer_ = null;
272 }
273 },
274
275 /**
276 * The index of the current track.
277 * If the list has no tracks, the value must be -1.
278 *
279 * @type {number}
280 */
281 get currentTrackIndex() {
282 return this.trackList.currentTrackIndex;
283 },
284 set currentTrackIndex(value) {
285 this.trackList.currentTrackIndex = value;
286 },
287
288 /**
289 * The list of the tracks in the playlist.
290 *
291 * When it changed, current operation including playback is stopped and
292 * restarts playback with new tracks if necessary.
293 *
294 * @type {Array.<AudioPlayer.TrackInfo>}
295 */
296 get tracks() {
297 return this.trackList ? this.trackList.tracks : null;
298 },
299 set tracks(tracks) {
300 if (this.trackList.tracks === tracks)
301 return;
302
303 this.cancelAutoAdvance_();
304
305 this.trackList.tracks = tracks;
306 var currentTrack = this.trackList.getCurrentTrack();
307 if (currentTrack && currentTrack.url != this.audioElement.src) {
308 this.audioElement.src = currentTrack.url;
309 this.audioElement.play();
310 }
311 },
312
313 /**
314 * Invoked when the audio player is being unloaded.
315 */
316 onPageUnload: function() {
317 this.audioElement.src = ''; // Hack to prevent crashing.
318 },
319
320 /**
321 * Invoked the 'keydown' event is fired.
322 * @param {Event} event The event object.
323 */
324 onKeyDown_: function(event) {
325 switch (event.keyIdentifier) {
326 case 'Up':
327 if (this.audioController.volumeSliderShown && this.model.volume < 100)
328 this.model.volume += 1;
329 break;
330 case 'Down':
331 if (this.audioController.volumeSliderShown && this.model.volume > 0)
332 this.model.volume -= 1;
333 break;
334 case 'PageUp':
335 if (this.audioController.volumeSliderShown && this.model.volume < 91)
336 this.model.volume += 10;
337 break;
338 case 'PageDown':
339 if (this.audioController.volumeSliderShown && this.model.volume > 9)
340 this.model.volume -= 10;
341 break;
342 }
343 },
344 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698