1 // Copyright 2014 Google Inc. All rights reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 (function(shared, scope, testing) {
16 scope.Player = function(source) {
19 // FIXME: detach existing player.
22 this._isGroup = false;
24 this._childPlayers = [];
25 this._callback = null;
26 this._rebuildUnderlyingPlayer();
27 // Players are constructed in the idle state.
28 this._player.cancel();
31 // TODO: add a source getter/setter
32 scope.Player.prototype = {
33 _rebuildUnderlyingPlayer: function() {
35 this._player.cancel();
39 if (!this.source || this.source instanceof window.Animation) {
40 this._player = scope.newUnderlyingPlayerForAnimation(this.source);
41 scope.bindPlayerForAnimation(this);
43 if (this.source instanceof window.AnimationSequence || this.source instanceof window.AnimationGroup) {
44 this._player = scope.newUnderlyingPlayerForGroup(this.source);
45 scope.bindPlayerForGroup(this);
48 // FIXME: move existing currentTime/startTime/playState to new player
51 return this._player.paused;
54 return this._player.playState;
57 return this._onfinish;
60 if (typeof v == 'function') {
62 this._player.onfinish = (function(e) {
67 this._player.onfinish = v;
68 this.onfinish = this._player.onfinish;
72 return this._player.currentTime;
75 this._player.currentTime = v;
77 this._forEachChild(function(child, offset) {
78 child.currentTime = v - offset;
82 return this._player.startTime;
85 this._player.startTime = v;
87 this._forEachChild(function(child, offset) {
88 child.startTime = v + offset;
92 return this._player.playbackRate;
95 return this._player.finished;
100 scope.awaitStartTime(this);
101 this._forEachChild(function(child) {
102 var time = child.currentTime;
104 child.currentTime = time;
108 this._player.pause();
110 this._forEachChild(function(child) {
115 this._player.finish();
117 // TODO: child players??
120 this._player.cancel();
122 this._removePlayers();
124 reverse: function() {
125 this._player.reverse();
126 scope.awaitStartTime(this);
128 this._forEachChild(function(child, offset) {
130 child.startTime = this.startTime + offset * this.playbackRate;
131 child.currentTime = this.currentTime + offset * this.playbackRate;
134 addEventListener: function(type, handler) {
135 var wrapped = handler;
136 if (typeof handler == 'function') {
137 wrapped = (function(e) {
139 handler.call(this, e);
141 handler._wrapper = wrapped;
143 this._player.addEventListener(type, wrapped);
145 removeEventListener: function(type, handler) {
146 this._player.removeEventListener(type, (handler && handler._wrapper) || handler);
148 _removePlayers: function() {
149 while (this._childPlayers.length)
150 this._childPlayers.pop().cancel();
152 _forEachChild: function(f) {
154 this._childPlayers.forEach(function(child) {
155 f.call(this, child, offset);
156 if (this.source instanceof window.AnimationSequence)
157 offset += child.source.activeDuration;
162 })(webAnimationsShared, webAnimationsNext, webAnimationsTesting);