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 * @fileoverview MediaControls class implements media playback controls | 6 * @fileoverview MediaControls class implements media playback controls |
7 * that exist outside of the audio/video HTML element. | 7 * that exist outside of the audio/video HTML element. |
8 */ | 8 */ |
9 | 9 |
10 /** | 10 /** |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 */ | 50 */ |
51 this.textBanner_ = null; | 51 this.textBanner_ = null; |
52 | 52 |
53 /** | 53 /** |
54 * @type {HTMLElement} | 54 * @type {HTMLElement} |
55 * @private | 55 * @private |
56 */ | 56 */ |
57 this.soundButton_ = null; | 57 this.soundButton_ = null; |
58 | 58 |
59 /** | 59 /** |
| 60 * @type {HTMLElement} |
| 61 * @private |
| 62 */ |
| 63 this.subtitlesButton_ = null; |
| 64 |
| 65 /** |
| 66 * @private {TextTrack} |
| 67 */ |
| 68 this.subtitlesTrack_ = null; |
| 69 |
| 70 /** |
60 * @type {boolean} | 71 * @type {boolean} |
61 * @private | 72 * @private |
62 */ | 73 */ |
63 this.resumeAfterDrag_ = false; | 74 this.resumeAfterDrag_ = false; |
64 | 75 |
65 /** | 76 /** |
66 * @type {HTMLElement} | 77 * @type {HTMLElement} |
67 * @private | 78 * @private |
68 */ | 79 */ |
69 this.currentTime_ = null; | 80 this.currentTime_ = null; |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 | 522 |
512 /** | 523 /** |
513 * @private | 524 * @private |
514 */ | 525 */ |
515 MediaControls.prototype.onVolumeDrag_ = function() { | 526 MediaControls.prototype.onVolumeDrag_ = function() { |
516 if (this.media_.volume !== 0) { | 527 if (this.media_.volume !== 0) { |
517 this.savedVolume_ = this.media_.volume; | 528 this.savedVolume_ = this.media_.volume; |
518 } | 529 } |
519 }; | 530 }; |
520 | 531 |
| 532 /** |
| 533 * Initializes subtitles button. |
| 534 */ |
| 535 MediaControls.prototype.initSubtitlesButton = function() { |
| 536 this.subtitlesTrack_ = null; |
| 537 this.subtitlesButton_ = |
| 538 this.createButton('subtitles', this.onSubtitlesButtonClicked_.bind(this)); |
| 539 this.subtitlesButton_.setAttribute('aria-label', |
| 540 str('VIDEO_PLAYER_SUBTITLES_BUTTON_LABEL')); |
| 541 }; |
| 542 |
| 543 /** |
| 544 * @param {Event} event Mouse click event. |
| 545 * @private |
| 546 */ |
| 547 MediaControls.prototype.onSubtitlesButtonClicked_ = function(event) { |
| 548 if (!this.subtitlesTrack_) { |
| 549 return; |
| 550 } |
| 551 this.toggleSubtitlesMode_(this.subtitlesTrack_.mode === 'hidden'); |
| 552 }; |
| 553 |
| 554 /** |
| 555 * @param {boolean} on Whether enabled or not. |
| 556 * @private |
| 557 */ |
| 558 MediaControls.prototype.toggleSubtitlesMode_ = function(on) { |
| 559 if (!this.subtitlesTrack_) { |
| 560 return; |
| 561 } |
| 562 if (on) { |
| 563 this.subtitlesTrack_.mode = 'showing'; |
| 564 this.subtitlesButton_.setAttribute('showing', ''); |
| 565 } else { |
| 566 this.subtitlesTrack_.mode = 'hidden'; |
| 567 this.subtitlesButton_.removeAttribute('showing'); |
| 568 } |
| 569 }; |
| 570 |
| 571 /** |
| 572 * @param {TextTrack} track Subtitles track |
| 573 * @private |
| 574 */ |
| 575 MediaControls.prototype.attachTextTrack_ = function(track) { |
| 576 this.subtitlesTrack_ = track; |
| 577 if (this.subtitlesTrack_) { |
| 578 this.toggleSubtitlesMode_(true); |
| 579 this.subtitlesButton_.removeAttribute('unavailable'); |
| 580 } else { |
| 581 this.subtitlesButton_.setAttribute('unavailable', ''); |
| 582 } |
| 583 }; |
| 584 |
| 585 /** |
| 586 * @private |
| 587 */ |
| 588 MediaControls.prototype.detachTextTrack_ = function() { |
| 589 this.subtitlesTrack_ = null; |
| 590 }; |
| 591 |
521 /* | 592 /* |
522 * Media event handlers. | 593 * Media event handlers. |
523 */ | 594 */ |
524 | 595 |
525 /** | 596 /** |
526 * Attach a media element. | 597 * Attach a media element. |
527 * | 598 * |
528 * @param {!HTMLMediaElement} mediaElement The media element to control. | 599 * @param {!HTMLMediaElement} mediaElement The media element to control. |
529 */ | 600 */ |
530 MediaControls.prototype.attachMedia = function(mediaElement) { | 601 MediaControls.prototype.attachMedia = function(mediaElement) { |
(...skipping 10 matching lines...) Expand all Loading... |
541 this.textBanner_.removeAttribute('visible'); | 612 this.textBanner_.removeAttribute('visible'); |
542 | 613 |
543 // Reflect the media state in the UI. | 614 // Reflect the media state in the UI. |
544 this.onMediaDuration_(); | 615 this.onMediaDuration_(); |
545 this.onMediaPlay_(this.isPlaying()); | 616 this.onMediaPlay_(this.isPlaying()); |
546 this.onMediaProgress_(); | 617 this.onMediaProgress_(); |
547 if (this.volume_) { | 618 if (this.volume_) { |
548 /* Copy the user selected volume to the new media element. */ | 619 /* Copy the user selected volume to the new media element. */ |
549 this.savedVolume_ = this.media_.volume = this.volume_.ratio; | 620 this.savedVolume_ = this.media_.volume = this.volume_.ratio; |
550 } | 621 } |
| 622 if (this.media_.textTracks.length > 0) { |
| 623 this.attachTextTrack_(this.media_.textTracks[0]); |
| 624 } else { |
| 625 this.attachTextTrack_(null); |
| 626 } |
551 }; | 627 }; |
552 | 628 |
553 /** | 629 /** |
554 * Detach media event handlers. | 630 * Detach media event handlers. |
555 */ | 631 */ |
556 MediaControls.prototype.detachMedia = function() { | 632 MediaControls.prototype.detachMedia = function() { |
557 if (!this.media_) | 633 if (!this.media_) |
558 return; | 634 return; |
559 | 635 |
560 this.media_.removeEventListener('play', this.onMediaPlayBound_); | 636 this.media_.removeEventListener('play', this.onMediaPlayBound_); |
561 this.media_.removeEventListener('pause', this.onMediaPauseBound_); | 637 this.media_.removeEventListener('pause', this.onMediaPauseBound_); |
562 this.media_.removeEventListener('durationchange', this.onMediaDurationBound_); | 638 this.media_.removeEventListener('durationchange', this.onMediaDurationBound_); |
563 this.media_.removeEventListener('timeupdate', this.onMediaProgressBound_); | 639 this.media_.removeEventListener('timeupdate', this.onMediaProgressBound_); |
564 this.media_.removeEventListener('error', this.onMediaError_); | 640 this.media_.removeEventListener('error', this.onMediaError_); |
565 | 641 |
566 this.media_ = null; | 642 this.media_ = null; |
| 643 this.detachTextTrack_(); |
567 }; | 644 }; |
568 | 645 |
569 /** | 646 /** |
570 * Force-empty the media pipeline. This is a workaround for crbug.com/149957. | 647 * Force-empty the media pipeline. This is a workaround for crbug.com/149957. |
571 * The document is not going to be GC-ed until the last Files app window closes, | 648 * The document is not going to be GC-ed until the last Files app window closes, |
572 * but we want the media pipeline to deinitialize ASAP to minimize leakage. | 649 * but we want the media pipeline to deinitialize ASAP to minimize leakage. |
573 */ | 650 */ |
574 MediaControls.prototype.cleanup = function() { | 651 MediaControls.prototype.cleanup = function() { |
575 if (!this.media_) | 652 if (!this.media_) |
576 return; | 653 return; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 * @extends {MediaControls} | 813 * @extends {MediaControls} |
737 */ | 814 */ |
738 function VideoControls( | 815 function VideoControls( |
739 containerElement, onMediaError, opt_fullScreenToggle, opt_stateIconParent) { | 816 containerElement, onMediaError, opt_fullScreenToggle, opt_stateIconParent) { |
740 MediaControls.call(this, containerElement, onMediaError); | 817 MediaControls.call(this, containerElement, onMediaError); |
741 | 818 |
742 this.container_.classList.add('video-controls'); | 819 this.container_.classList.add('video-controls'); |
743 this.initPlayButton(); | 820 this.initPlayButton(); |
744 this.initTimeControls(); | 821 this.initTimeControls(); |
745 this.initVolumeControls(); | 822 this.initVolumeControls(); |
| 823 this.initSubtitlesButton(); |
746 | 824 |
747 // Create the cast button. | 825 // Create the cast button. |
748 // We need to use <button> since cr.ui.MenuButton.decorate modifies prototype | 826 // We need to use <button> since cr.ui.MenuButton.decorate modifies prototype |
749 // chain, by which <files-icon-button> will not work correctly. | 827 // chain, by which <files-icon-button> will not work correctly. |
750 // TODO(fukino): Find a way to use files-icon-button consistently. | 828 // TODO(fukino): Find a way to use files-icon-button consistently. |
751 this.castButton_ = this.createControl( | 829 this.castButton_ = this.createControl( |
752 'cast media-button', undefined, 'button'); | 830 'cast media-button', undefined, 'button'); |
753 this.castButton_.setAttribute('menu', '#cast-menu'); | 831 this.castButton_.setAttribute('menu', '#cast-menu'); |
754 this.castButton_.setAttribute('aria-label', str('VIDEO_PLAYER_PLAY_ON')); | 832 this.castButton_.setAttribute('aria-label', str('VIDEO_PLAYER_PLAY_ON')); |
755 this.castButton_.setAttribute('state', MediaControls.ButtonStateType.DEFAULT); | 833 this.castButton_.setAttribute('state', MediaControls.ButtonStateType.DEFAULT); |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
963 } else { | 1041 } else { |
964 this.container_.removeAttribute('fullscreen'); | 1042 this.container_.removeAttribute('fullscreen'); |
965 } | 1043 } |
966 | 1044 |
967 if (this.fullscreenButton_) { | 1045 if (this.fullscreenButton_) { |
968 this.fullscreenButton_.setAttribute('aria-label', | 1046 this.fullscreenButton_.setAttribute('aria-label', |
969 fullscreen ? str('VIDEO_PLAYER_EXIT_FULL_SCREEN_BUTTON_LABEL') | 1047 fullscreen ? str('VIDEO_PLAYER_EXIT_FULL_SCREEN_BUTTON_LABEL') |
970 : str('VIDEO_PLAYER_FULL_SCREEN_BUTTON_LABEL'));; | 1048 : str('VIDEO_PLAYER_FULL_SCREEN_BUTTON_LABEL'));; |
971 } | 1049 } |
972 }; | 1050 }; |
OLD | NEW |