| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Overrided metadata worker's path. | 6 * Overrided metadata worker's path. |
| 7 * @type {string} | 7 * @type {string} |
| 8 * @const | 8 * @const |
| 9 */ | 9 */ |
| 10 ContentMetadataProvider.WORKER_SCRIPT = '/js/metadata_worker.js'; | 10 ContentMetadataProvider.WORKER_SCRIPT = '/js/metadata_worker.js'; |
| 11 | 11 |
| 12 /** | 12 /** |
| 13 * @param {HTMLElement} container Container element. | 13 * @param {HTMLElement} container Container element. |
| 14 * @constructor | 14 * @constructor |
| 15 */ | 15 */ |
| 16 function AudioPlayer(container) { | 16 function AudioPlayer(container) { |
| 17 this.container_ = container; | 17 this.container_ = container; |
| 18 this.volumeManager_ = new VolumeManagerWrapper( | 18 this.volumeManager_ = new VolumeManagerWrapper( |
| 19 VolumeManagerWrapper.DriveEnabledStatus.DRIVE_ENABLED); | 19 VolumeManagerWrapper.DriveEnabledStatus.DRIVE_ENABLED); |
| 20 this.metadataModel_ = new MetadataModel.create(this.volumeManager_); | 20 this.metadataModel_ = new MetadataModel.create(this.volumeManager_); |
| 21 this.selectedEntry_ = null; | 21 this.selectedEntry_ = null; |
| 22 | 22 |
| 23 this.model_ = new AudioPlayerModel(); | 23 this.model_ = new AudioPlayerModel(); |
| 24 var observer = new PathObserver(this.model_, 'expanded'); | 24 Object.observe(this.model_, function(changes) { |
| 25 observer.open(function(newValue, oldValue) { | 25 for (var i = 0; i < changes.lenfth; i++) { |
| 26 // Inverse arguments intentionally to match the Polymer way. | 26 var change = changes[i]; |
| 27 this.onModelExpandedChanged(oldValue, newValue); | 27 if (change.name == 'expanded' && change.type == 'update') { |
| 28 this.onModelExpandedChanged(change.oldValue, change.object.expanded); |
| 29 break; |
| 30 } |
| 31 } |
| 28 }.bind(this)); | 32 }.bind(this)); |
| 29 | 33 |
| 30 this.entries_ = []; | 34 this.entries_ = []; |
| 31 this.currentTrackIndex_ = -1; | 35 this.currentTrackIndex_ = -1; |
| 32 this.playlistGeneration_ = 0; | 36 this.playlistGeneration_ = 0; |
| 33 | 37 |
| 34 /** | 38 /** |
| 35 * Whether if the playlist is expanded or not. This value is changed by | 39 * Whether if the playlist is expanded or not. This value is changed by |
| 36 * this.syncExpanded(). | 40 * this.syncExpanded(). |
| 37 * True: expanded, false: collapsed, null: unset. | 41 * True: expanded, false: collapsed, null: unset. |
| 38 * | 42 * |
| 39 * @type {?boolean} | 43 * @type {?boolean} |
| 40 * @private | 44 * @private |
| 41 */ | 45 */ |
| 42 this.isExpanded_ = null; // Initial value is null. It'll be set in load(). | 46 this.isExpanded_ = null; // Initial value is null. It'll be set in load(). |
| 43 | 47 |
| 44 this.player_ = document.querySelector('audio-player'); | 48 this.player_ = document.querySelector('audio-player'); |
| 45 // TODO(yoshiki): Move tracks into the model. | 49 // TODO(yoshiki): Move tracks into the model. |
| 46 this.player_.tracks = []; | 50 this.player_.tracks = []; |
| 47 this.player_.model = this.model_; | 51 this.player_.model = this.model_; |
| 48 Platform.performMicrotaskCheckpoint(); | |
| 49 | 52 |
| 50 this.errorString_ = ''; | 53 // Run asynchronously after an event of model change is delivered. |
| 51 this.offlineString_ = ''; | 54 setTimeout(function() { |
| 52 chrome.fileManagerPrivate.getStrings(function(strings) { | 55 this.errorString_ = ''; |
| 53 container.ownerDocument.title = strings['AUDIO_PLAYER_TITLE']; | 56 this.offlineString_ = ''; |
| 54 this.errorString_ = strings['AUDIO_ERROR']; | 57 chrome.fileManagerPrivate.getStrings(function(strings) { |
| 55 this.offlineString_ = strings['AUDIO_OFFLINE']; | 58 container.ownerDocument.title = strings['AUDIO_PLAYER_TITLE']; |
| 56 AudioPlayer.TrackInfo.DEFAULT_ARTIST = | 59 this.errorString_ = strings['AUDIO_ERROR']; |
| 57 strings['AUDIO_PLAYER_DEFAULT_ARTIST']; | 60 this.offlineString_ = strings['AUDIO_OFFLINE']; |
| 61 AudioPlayer.TrackInfo.DEFAULT_ARTIST = |
| 62 strings['AUDIO_PLAYER_DEFAULT_ARTIST']; |
| 63 }.bind(this)); |
| 64 |
| 65 this.volumeManager_.addEventListener('externally-unmounted', |
| 66 this.onExternallyUnmounted_.bind(this)); |
| 67 |
| 68 window.addEventListener('resize', this.onResize_.bind(this)); |
| 69 |
| 70 // Show the window after DOM is processed. |
| 71 var currentWindow = chrome.app.window.current(); |
| 72 if (currentWindow) |
| 73 setTimeout(currentWindow.show.bind(currentWindow), 0); |
| 58 }.bind(this)); | 74 }.bind(this)); |
| 59 | |
| 60 this.volumeManager_.addEventListener('externally-unmounted', | |
| 61 this.onExternallyUnmounted_.bind(this)); | |
| 62 | |
| 63 window.addEventListener('resize', this.onResize_.bind(this)); | |
| 64 | |
| 65 // Show the window after DOM is processed. | |
| 66 var currentWindow = chrome.app.window.current(); | |
| 67 if (currentWindow) | |
| 68 setTimeout(currentWindow.show.bind(currentWindow), 0); | |
| 69 } | 75 } |
| 70 | 76 |
| 71 /** | 77 /** |
| 72 * Initial load method (static). | 78 * Initial load method (static). |
| 73 */ | 79 */ |
| 74 AudioPlayer.load = function() { | 80 AudioPlayer.load = function() { |
| 75 document.ondragstart = function(e) { e.preventDefault(); }; | 81 document.ondragstart = function(e) { e.preventDefault(); }; |
| 76 | 82 |
| 77 AudioPlayer.instance = | 83 AudioPlayer.instance = |
| 78 new AudioPlayer(document.querySelector('.audio-player')); | 84 new AudioPlayer(document.querySelector('.audio-player')); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 | 133 |
| 128 for (var i = 0; i != this.entries_.length; i++) { | 134 for (var i = 0; i != this.entries_.length; i++) { |
| 129 var entry = this.entries_[i]; | 135 var entry = this.entries_[i]; |
| 130 var onClick = this.select_.bind(this, i); | 136 var onClick = this.select_.bind(this, i); |
| 131 newTracks.push(new AudioPlayer.TrackInfo(entry, onClick)); | 137 newTracks.push(new AudioPlayer.TrackInfo(entry, onClick)); |
| 132 | 138 |
| 133 if (unchanged && entry.toURL() !== currentTracks[i].url) | 139 if (unchanged && entry.toURL() !== currentTracks[i].url) |
| 134 unchanged = false; | 140 unchanged = false; |
| 135 } | 141 } |
| 136 | 142 |
| 137 if (!unchanged) { | 143 if (!unchanged) |
| 138 this.player_.tracks = newTracks; | 144 this.player_.tracks = newTracks; |
| 139 | 145 |
| 140 // Makes it sure that the handler of the track list is called, before | 146 // Run asynchronously, to makes it sure that the handler of the track list |
| 141 // the handler of the track index. | 147 // is called, before the handler of the track index. |
| 142 Platform.performMicrotaskCheckpoint(); | 148 setTimeout(function() { |
| 143 } | 149 this.select_(position, !!time); |
| 144 | 150 |
| 145 this.select_(position, !!time); | 151 // Load the selected track metadata first, then load the rest. |
| 146 | 152 this.loadMetadata_(position); |
| 147 // Load the selected track metadata first, then load the rest. | 153 for (i = 0; i != this.entries_.length; i++) { |
| 148 this.loadMetadata_(position); | 154 if (i != position) |
| 149 for (i = 0; i != this.entries_.length; i++) { | 155 this.loadMetadata_(i); |
| 150 if (i != position) | 156 } |
| 151 this.loadMetadata_(i); | 157 }.bind(this)); |
| 152 } | |
| 153 }.bind(this)); | 158 }.bind(this)); |
| 154 }.bind(this)); | 159 }.bind(this)); |
| 155 }; | 160 }; |
| 156 | 161 |
| 157 /** | 162 /** |
| 158 * Loads metadata for a track. | 163 * Loads metadata for a track. |
| 159 * @param {number} track Track number. | 164 * @param {number} track Track number. |
| 160 * @private | 165 * @private |
| 161 */ | 166 */ |
| 162 AudioPlayer.prototype.loadMetadata_ = function(track) { | 167 AudioPlayer.prototype.loadMetadata_ = function(track) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 * @param {number} newTrack New track number. | 210 * @param {number} newTrack New track number. |
| 206 * @param {number} time New playback position (in second). | 211 * @param {number} time New playback position (in second). |
| 207 * @private | 212 * @private |
| 208 */ | 213 */ |
| 209 AudioPlayer.prototype.select_ = function(newTrack, time) { | 214 AudioPlayer.prototype.select_ = function(newTrack, time) { |
| 210 if (this.currentTrackIndex_ == newTrack) return; | 215 if (this.currentTrackIndex_ == newTrack) return; |
| 211 | 216 |
| 212 this.currentTrackIndex_ = newTrack; | 217 this.currentTrackIndex_ = newTrack; |
| 213 this.player_.currentTrackIndex = this.currentTrackIndex_; | 218 this.player_.currentTrackIndex = this.currentTrackIndex_; |
| 214 this.player_.audioController.time = time; | 219 this.player_.audioController.time = time; |
| 215 Platform.performMicrotaskCheckpoint(); | |
| 216 | 220 |
| 217 if (!window.appReopen) | 221 // Run asynchronously after an event of current track change is delivered. |
| 218 this.player_.audioElement.play(); | 222 setTimeout(function() { |
| 223 if (!window.appReopen) |
| 224 this.player_.audioElement.play(); |
| 219 | 225 |
| 220 window.appState.position = this.currentTrackIndex_; | 226 window.appState.position = this.currentTrackIndex_; |
| 221 window.appState.time = 0; | 227 window.appState.time = 0; |
| 222 util.saveAppState(); | 228 util.saveAppState(); |
| 223 | 229 |
| 224 var entry = this.entries_[this.currentTrackIndex_]; | 230 var entry = this.entries_[this.currentTrackIndex_]; |
| 225 | 231 |
| 226 this.fetchMetadata_(entry, function(metadata) { | 232 this.fetchMetadata_(entry, function(metadata) { |
| 227 if (this.currentTrackIndex_ != newTrack) | 233 if (this.currentTrackIndex_ != newTrack) |
| 228 return; | 234 return; |
| 229 | 235 |
| 230 this.selectedEntry_ = entry; | 236 this.selectedEntry_ = entry; |
| 237 }.bind(this)); |
| 231 }.bind(this)); | 238 }.bind(this)); |
| 232 }; | 239 }; |
| 233 | 240 |
| 234 /** | 241 /** |
| 235 * @param {FileEntry} entry Track file entry. | 242 * @param {FileEntry} entry Track file entry. |
| 236 * @param {function(object)} callback Callback. | 243 * @param {function(object)} callback Callback. |
| 237 * @private | 244 * @private |
| 238 */ | 245 */ |
| 239 AudioPlayer.prototype.fetchMetadata_ = function(entry, callback) { | 246 AudioPlayer.prototype.fetchMetadata_ = function(entry, callback) { |
| 240 this.metadataModel_.get( | 247 this.metadataModel_.get( |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 // TODO(yoshiki): Handle error in better way. | 431 // TODO(yoshiki): Handle error in better way. |
| 425 // TODO(yoshiki): implement artwork (metadata.thumbnail) | 432 // TODO(yoshiki): implement artwork (metadata.thumbnail) |
| 426 this.title = metadata.mediaTitle || this.getDefaultTitle(); | 433 this.title = metadata.mediaTitle || this.getDefaultTitle(); |
| 427 this.artist = error || metadata.mediaArtist || this.getDefaultArtist(); | 434 this.artist = error || metadata.mediaArtist || this.getDefaultArtist(); |
| 428 }; | 435 }; |
| 429 | 436 |
| 430 // Starts loading the audio player. | 437 // Starts loading the audio player. |
| 431 window.addEventListener('polymer-ready', function(e) { | 438 window.addEventListener('polymer-ready', function(e) { |
| 432 AudioPlayer.load(); | 439 AudioPlayer.load(); |
| 433 }); | 440 }); |
| OLD | NEW |