|
110
|
1 |
// A global callback for youtube... that makes me angry |
|
|
2 |
var onYouTubePlayerReady = function( containerId ) { |
|
|
3 |
|
|
|
4 |
onYouTubePlayerReady[ containerId ] && onYouTubePlayerReady[ containerId ](); |
|
|
5 |
}; |
|
|
6 |
onYouTubePlayerReady.stateChangeEventHandler = {}; |
|
|
7 |
|
|
|
8 |
Popcorn.player( "youtube", { |
|
|
9 |
_setup: function( options ) { |
|
|
10 |
|
|
|
11 |
var media = this, |
|
|
12 |
youtubeObject, |
|
|
13 |
container = document.createElement( "div" ), |
|
|
14 |
currentTime = 0, |
|
|
15 |
seekTime = 0, |
|
|
16 |
seeking = false, |
|
|
17 |
|
|
|
18 |
// state code for volume changed polling |
|
|
19 |
volumeChanged = false, |
|
|
20 |
lastMuted = false, |
|
|
21 |
lastVolume = 0; |
|
|
22 |
|
|
|
23 |
container.id = media.id + Popcorn.guid(); |
|
|
24 |
|
|
|
25 |
media.appendChild( container ); |
|
|
26 |
|
|
|
27 |
var youtubeInit = function() { |
|
|
28 |
|
|
|
29 |
var flashvars, |
|
|
30 |
params, |
|
|
31 |
attributes, |
|
|
32 |
src; |
|
|
33 |
|
|
|
34 |
// expose a callback to this scope, that is called from the global callback youtube calls |
|
|
35 |
onYouTubePlayerReady[ container.id ] = function() { |
|
|
36 |
|
|
|
37 |
youtubeObject = document.getElementById( container.id ); |
|
|
38 |
|
|
|
39 |
// more youtube callback nonsense |
|
|
40 |
onYouTubePlayerReady.stateChangeEventHandler[ container.id ] = function( state ) { |
|
|
41 |
|
|
|
42 |
// playing is state 1 |
|
|
43 |
// paused is state 2 |
|
|
44 |
if ( state === 1 ) { |
|
|
45 |
|
|
|
46 |
media.paused && media.play(); |
|
|
47 |
// youtube fires paused events while seeking |
|
|
48 |
// this is the only way to get seeking events |
|
|
49 |
} else if ( state === 2 ) { |
|
|
50 |
|
|
|
51 |
// silly logic forced on me by the youtube API |
|
|
52 |
// calling youtube.seekTo triggers multiple events |
|
|
53 |
// with the second events getCurrentTime being the old time |
|
|
54 |
if ( seeking && seekTime === currentTime && seekTime !== youtubeObject.getCurrentTime() ) { |
|
|
55 |
|
|
|
56 |
seeking = false; |
|
|
57 |
youtubeObject.seekTo( currentTime ); |
|
|
58 |
return; |
|
|
59 |
} |
|
|
60 |
|
|
|
61 |
currentTime = youtubeObject.getCurrentTime(); |
|
|
62 |
media.dispatchEvent( "timeupdate" ); |
|
|
63 |
!media.paused && media.pause(); |
|
|
64 |
} |
|
|
65 |
}; |
|
|
66 |
|
|
|
67 |
// youtube requires callbacks to be a string to a function path from the global scope |
|
|
68 |
youtubeObject.addEventListener( "onStateChange", "onYouTubePlayerReady.stateChangeEventHandler." + container.id ); |
|
|
69 |
|
|
|
70 |
var timeupdate = function() { |
|
|
71 |
|
|
|
72 |
if ( !media.paused ) { |
|
|
73 |
|
|
|
74 |
currentTime = youtubeObject.getCurrentTime(); |
|
|
75 |
media.dispatchEvent( "timeupdate" ); |
|
|
76 |
setTimeout( timeupdate, 10 ); |
|
|
77 |
} |
|
|
78 |
}; |
|
|
79 |
|
|
|
80 |
var volumeupdate = function() { |
|
|
81 |
|
|
|
82 |
if ( lastMuted !== youtubeObject.isMuted() ) { |
|
|
83 |
|
|
|
84 |
lastMuted = youtubeObject.isMuted(); |
|
|
85 |
media.dispatchEvent( "volumechange" ); |
|
|
86 |
} |
|
|
87 |
|
|
|
88 |
if ( lastVolume !== youtubeObject.getVolume() ) { |
|
|
89 |
|
|
|
90 |
lastVolume = youtubeObject.getVolume(); |
|
|
91 |
media.dispatchEvent( "volumechange" ); |
|
|
92 |
} |
|
|
93 |
|
|
|
94 |
setTimeout( volumeupdate, 250 ); |
|
|
95 |
}; |
|
|
96 |
|
|
|
97 |
media.play = function() { |
|
|
98 |
|
|
|
99 |
media.paused = false; |
|
|
100 |
media.dispatchEvent( "play" ); |
|
|
101 |
|
|
|
102 |
media.dispatchEvent( "playing" ); |
|
|
103 |
timeupdate(); |
|
|
104 |
youtubeObject.playVideo(); |
|
|
105 |
}; |
|
|
106 |
|
|
|
107 |
media.pause = function() { |
|
|
108 |
|
|
|
109 |
if ( !media.paused ) { |
|
|
110 |
|
|
|
111 |
media.paused = true; |
|
|
112 |
media.dispatchEvent( "pause" ); |
|
|
113 |
youtubeObject.pauseVideo(); |
|
|
114 |
} |
|
|
115 |
}; |
|
|
116 |
|
|
|
117 |
Popcorn.player.defineProperty( media, "currentTime", { |
|
|
118 |
set: function( val ) { |
|
|
119 |
|
|
|
120 |
// make sure val is a number |
|
|
121 |
currentTime = seekTime = +val; |
|
|
122 |
seeking = true; |
|
|
123 |
media.dispatchEvent( "seeked" ); |
|
|
124 |
media.dispatchEvent( "timeupdate" ); |
|
|
125 |
youtubeObject.seekTo( currentTime ); |
|
|
126 |
return currentTime; |
|
|
127 |
}, |
|
|
128 |
get: function() { |
|
|
129 |
|
|
|
130 |
return currentTime; |
|
|
131 |
} |
|
|
132 |
}); |
|
|
133 |
|
|
|
134 |
Popcorn.player.defineProperty( media, "muted", { |
|
|
135 |
set: function( val ) { |
|
|
136 |
|
|
|
137 |
if ( youtubeObject.isMuted() !== val ) { |
|
|
138 |
|
|
|
139 |
if ( val ) { |
|
|
140 |
|
|
|
141 |
youtubeObject.mute(); |
|
|
142 |
} else { |
|
|
143 |
|
|
|
144 |
youtubeObject.unMute(); |
|
|
145 |
} |
|
|
146 |
|
|
|
147 |
lastMuted = youtubeObject.isMuted(); |
|
|
148 |
media.dispatchEvent( "volumechange" ); |
|
|
149 |
} |
|
|
150 |
|
|
|
151 |
return youtubeObject.isMuted(); |
|
|
152 |
}, |
|
|
153 |
get: function() { |
|
|
154 |
|
|
|
155 |
return youtubeObject.isMuted(); |
|
|
156 |
} |
|
|
157 |
}); |
|
|
158 |
|
|
|
159 |
Popcorn.player.defineProperty( media, "volume", { |
|
|
160 |
set: function( val ) { |
|
|
161 |
|
|
|
162 |
if ( youtubeObject.getVolume() !== val ) { |
|
|
163 |
|
|
|
164 |
youtubeObject.setVolume( val ); |
|
|
165 |
lastVolume = youtubeObject.getVolume(); |
|
|
166 |
media.dispatchEvent( "volumechange" ); |
|
|
167 |
} |
|
|
168 |
|
|
|
169 |
return youtubeObject.getVolume(); |
|
|
170 |
}, |
|
|
171 |
get: function() { |
|
|
172 |
|
|
|
173 |
return youtubeObject.getVolume(); |
|
|
174 |
} |
|
|
175 |
}); |
|
|
176 |
|
|
|
177 |
media.readyState = 4; |
|
|
178 |
media.dispatchEvent( "load" ); |
|
|
179 |
media.duration = youtubeObject.getDuration(); |
|
|
180 |
media.dispatchEvent( "durationchange" ); |
|
|
181 |
volumeupdate(); |
|
|
182 |
|
|
|
183 |
media.dispatchEvent( "loadeddata" ); |
|
|
184 |
}; |
|
|
185 |
|
|
|
186 |
options.controls = +options.controls === 0 || +options.controls === 1 ? options.controls : 1; |
|
|
187 |
options.annotations = +options.annotations === 1 || +options.annotations === 3 ? options.annotations : 1; |
|
|
188 |
|
|
|
189 |
flashvars = { |
|
|
190 |
playerapiid: container.id, |
|
|
191 |
controls: options.controls, |
|
|
192 |
iv_load_policy: options.annotations |
|
|
193 |
}; |
|
|
194 |
|
|
|
195 |
params = { |
|
|
196 |
wmode: "transparent", |
|
|
197 |
allowScriptAccess: "always" |
|
|
198 |
}; |
|
|
199 |
|
|
|
200 |
attributes = { |
|
|
201 |
id: container.id |
|
|
202 |
}; |
|
|
203 |
|
|
|
204 |
src = /^.*[\/=](.{11})/.exec( media.src )[ 1 ]; |
|
|
205 |
|
|
|
206 |
swfobject.embedSWF( "http://www.youtube.com/e/" + src + "?enablejsapi=1&playerapiid=" + container.id + "&version=3", |
|
|
207 |
container.id, media.offsetWidth, media.offsetHeight, "8", null, |
|
|
208 |
flashvars, params, attributes ); |
|
|
209 |
}; |
|
|
210 |
|
|
|
211 |
if ( !window.swfobject ) { |
|
|
212 |
|
|
|
213 |
Popcorn.getScript( "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js", youtubeInit ); |
|
|
214 |
} else { |
|
|
215 |
|
|
|
216 |
youtubeInit(); |
|
|
217 |
} |
|
|
218 |
} |
|
|
219 |
}); |
|
|
220 |
|