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

Unified Diff: chrome/browser/resources/file_manager/audio_player/elements/audio_player.js

Issue 144883002: [Files.app] Initial implementation of new audio player (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Separete the image files from this patch Created 6 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/file_manager/audio_player/elements/audio_player.js
diff --git a/chrome/browser/resources/file_manager/audio_player/elements/audio_player.js b/chrome/browser/resources/file_manager/audio_player/elements/audio_player.js
new file mode 100644
index 0000000000000000000000000000000000000000..1adf2a155f73f3e83de3c09707f918e040b39774
--- /dev/null
+++ b/chrome/browser/resources/file_manager/audio_player/elements/audio_player.js
@@ -0,0 +1,293 @@
+// Cpyright (c) 2013 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.
+
+'use strict';
+
+Polymer('audio-player', {
+ /**
+ * Child Elements
+ */
+ audioController: null,
+ audioElement: null,
+ trackList: null,
+
+ /**
+ * Initialize an element. This method is called automatically when the
+ * element is ready.
+ */
+ ready: function() {
+ this.audioController = this.$.audioController;
+ this.audioElement = this.$.audio;
+ this.trackList = this.$.trackList;
+
+ this.audioElement.volume = this.audioController.volume / 100;
+ this.audioElement.addEventListener('ended', this.onAudioEnded.bind(this));
+ this.audioElement.addEventListener('error', this.onAudioError.bind(this));
+
+ var onAudioStatusUpdatedBound = this.onAudioStatusUpdate_.bind(this);
+ this.audioElement.addEventListener('timeupdate', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('ended', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('play', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('pause', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('suspend', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('abort', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('error', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('emptied', onAudioStatusUpdatedBound);
+ this.audioElement.addEventListener('stalled', onAudioStatusUpdatedBound);
+ },
+
+ /**
+ * Register handlers for changing of external variables
+ */
+ observe: {
+ 'trackList.currentTrackIndex': 'onCurrentTrackIndexChanged',
+ 'audioController.playlistExpanded': 'onPlayerExpandedChanged',
+ 'audioController.playing': 'onControllerPlayingChanged',
+ 'audioController.volume': 'onControllerVolumeChanged',
+ 'audioController.time': 'onControllerTimeChanged',
+ 'audioController.shuffle': 'onControllerShuffleChanged',
+ 'audioController.repeat': 'onControllerRepeatChanged',
+ },
+
+ /**
+ * Invoked when trackList.currentTrackIndex is changed.
+ * @param {number} oldValue old value.
+ * @param {number} newValue new value.
+ */
+ onCurrentTrackIndexChanged: function(oldValue, newValue) {
+ if (oldValue != newValue) {
+ var currentTrack = this.trackList.getCurrentTrack();
+ if (currentTrack && currentTrack.url != this.audioElement.src) {
+ this.audioElement.src = currentTrack.url;
+ this.audioElement.play();
+ }
+ }
+ },
+
+ /**
+ * Invoked when audioController.playlistExpanded is changed.
+ * @param {boolean} oldValue old value.
+ * @param {boolean} newValue new value.
+ */
+ onPlayerExpandedChanged: function(oldValue, newValue) {
+ if (oldValue != newValue) {
+ this.trackList.expanded = newValue;
+ if (AudioPlayer.instance)
+ AudioPlayer.instance.syncExpanded();
+ }
+ },
+
+ /**
+ * Invoked when audioController.playing is changed.
+ * @param {boolean} oldValue old value.
+ * @param {boolean} newValue new value.
+ */
+ onControllerPlayingChanged: function(oldValue, newValue) {
+ if (newValue) {
+ if (!this.audioElement.src) {
+ var currentTrack = this.trackList.getCurrentTrack();
+ if (currentTrack && currentTrack.url != this.audioElement.src)
+ this.audioElement.src = currentTrack.url;
+ }
+
+ if (this.audioElement.src) {
+ this.audioElement.play();
+ return;
+ }
+ }
+
+ this.audioController.playing = false;
+ this.audioElement.pause();
+ },
+
+ /**
+ * Invoked when audioController.volume is changed.
+ * @param {number} oldValue old value.
+ * @param {number} newValue new value.
+ */
+ onControllerVolumeChanged: function(oldValue, newValue) {
+ this.audioElement.volume = newValue / 100;
+ },
+
+ /**
+ * Invoked when audioController.time is changed.
+ * @param {number} oldValue old value.
mtomasz 2014/01/23 08:05:09 nit: Please add a unit (ms?)
yoshiki 2014/01/24 15:34:19 Done.
+ * @param {number} newValue new value.
+ */
+ onControllerTimeChanged: function(oldValue, newValue) {
+ // Ignore periodical updates and small amount change.
+ if (Math.abs(oldValue - newValue) <= 500)
+ return;
+
+ if (this.audioElement.readyState !== 0)
+ this.audioElement.currentTime = this.audioController.time / 1000;
+ },
+
+ /**
+ * Invoked when audioController.shuffle is changed.
+ * @param {boolean} oldValue old value.
+ * @param {boolean} newValue new value.
+ */
+ onControllerShuffleChanged: function(oldValue, newValue) {
+ // TODO(yoshiki): Implement shuffle mode.
+ },
+
+ /**
+ * Invoked when audioController.repeat is changed.
+ * @param {boolean} oldValue old value.
+ * @param {boolean} newValue new value.
+ */
+ onControllerRepeatChanged: function(oldValue, newValue) {
+ this.trackList.repeat = newValue;
+ },
+
+ /**
+ * Invoked when the next button in the controller is clicked.
+ * This handler is registered in the 'on-click' attribute of the element.
+ */
+ onControllerNextClicked: function() {
+ this.advance_(true, true);
mtomasz 2014/01/23 08:05:09 Can we use an enum instead? It is hard to understa
yoshiki 2014/01/24 15:34:19 Done.
+ },
+
+ /**
+ * Invoked when the prev button in the controller is clicked.
+ * This handler is registered in the 'on-click' attribute of the element.
+ */
+ onControllerPreviousClicked: function() {
+ this.advance_(true, true);
+ },
+
+ /**
+ * Invoked when the playback in the audio element is ended.
+ * This handler is registered in this.ready().
+ */
+ onAudioEnded: function() {
+ this.advance_(true, this.audioController.repeat);
+ },
+
+ /**
+ * Invoked when the playback in the audio element gets error.
+ * This handler is registered in this.ready().
+ */
+ onAudioError: function() {
+ this.scheduleAutoAdvance_(true, this.audioController.repeat);
+ },
+
+ /**
+ * Invoked when the time of playback in the audio element is updated.
+ * This handler is registered in this.ready().
mtomasz 2014/01/23 08:05:09 @private missing
yoshiki 2014/01/24 15:34:19 Done.
+ */
+ onAudioStatusUpdate_: function() {
+ this.audioController.time = this.audioElement.currentTime * 1000;
+ this.audioController.duration = this.audioElement.duration * 1000;
+ this.audioController.playing = !this.audioElement.paused;
+ },
+
+ /**
+ * Go to the previous or the next track.
+ * @param {boolean} forward True if next, false if previous.
mtomasz 2014/01/23 08:05:09 One @param missing.
yoshiki 2014/01/24 15:34:19 Done.
+ * @private
+ */
+ advance_: function(forward, repeat) {
+ this.cancelAutoAdvance_();
+
+ var nextTrackIndex = this.trackList.getNextTrackIndex(forward);
+ var nextTrack = this.trackList.tracks[nextTrackIndex];
+ var isNextTrackAvailable = this.trackList.isNextTrackAvailable(forward);
+
+ this.trackList.currentTrackIndex = nextTrackIndex;
+
+ if (isNextTrackAvailable || repeat && nextTrack) {
+ this.audioElement.src = nextTrack.url;
+ this.audioElement.play();
+ } else {
+ this.audioElement.pause();
+ }
+ },
+
+ /**
+ * Timeout ID of auto advance. Used internally in scheduleAutoAdvance_() and
+ * cancelAutoAdvance_().
mtomasz 2014/01/23 08:05:09 No indent for jsdoc descriptions.
yoshiki 2014/01/24 15:34:19 Done.
mtomasz 2014/01/27 01:09:24 The indent still looks off.
+ * @type {number}
+ * @private
+ */
+ autoAdvanceTimer_: null,
+
+ /**
+ * Schedule automatic advance to the next track after a timeout.
mtomasz 2014/01/23 08:05:09 ditto: jsdoc missing
yoshiki 2014/01/24 15:34:19 Done.
+ * @private
+ */
+ scheduleAutoAdvance_: function(forward, repeat) {
+ this.cancelAutoAdvance_();
+ this.autoAdvanceTimer_ = setTimeout(
+ function() {
+ this.autoAdvanceTimer_ = null;
+ // We are advancing only if the next track is not known to be invalid.
+ // This prevents an endless auto-advancing in the case when all tracks
+ // are invalid (we will only visit each track once).
+ this.advance_(forward, repeat, true /* only if valid */);
+ }.bind(this),
+ 3000);
mtomasz 2014/01/23 08:05:09 Why do we need a timeout? I think users don't expe
yoshiki 2014/01/24 15:34:19 This gap happens when error is happened and the pl
+ },
+
+ /**
+ * Cancel the scheduled auto advance.
+ * @private
+ */
+ cancelAutoAdvance_: function() {
+ if (this.autoAdvanceTimer_) {
+ clearTimeout(this.autoAdvanceTimer_);
+ this.autoAdvanceTimer_ = null;
+ }
+ },
+
+ set currentTrackIndex(value) {
+ this.trackList.currentTrackIndex = value;
+ },
+ get currentTrackIndex() {
+ return this.trackList.currentTrackIndex;
+ },
+
+ /**
+ * Setter of 'tracks' property.
+ *
+ * This ends current operation including playback, and restarts playback if
mtomasz 2014/01/23 08:05:09 jsdoc missing.
yoshiki 2014/01/24 15:34:19 Done.
+ * necessary.
+ */
+ set tracks(tracks) {
+ if (this.trackList.tracks === tracks)
+ return;
+
+ this.cancelAutoAdvance_();
+
+ this.trackList.tracks = tracks;
+ var currentTrack = this.trackList.getCurrentTrack();
+ if (currentTrack && currentTrack.url != this.audioElement.src) {
+ this.audioElement.src = currentTrack.url;
+ this.audioElement.play();
+ }
+ },
+
+ /**
+ * Getter of 'tracks' property.
mtomasz 2014/01/23 08:05:09 ditto: jsdoc missing
yoshiki 2014/01/24 15:34:19 Done.
+ * This returns 'tracks' in the track list element.
+ */
+ get tracks() {
+ return this.trackList ? this.trackList.tracks : null;
+ },
+
+ /**
+ * Returns whether the track list is expanded or not.
+ */
+ isExpanded: function() {
+ return this.audioController.playlistExpanded;
+ },
+
+ /**
+ * Expands or collapse the track list.
+ */
+ expand: function(expand) {
+ this.audioController.playlistExpanded = !!expand;
+ }
+});

Powered by Google App Engine
This is Rietveld 408576698