Use common implementations of xhr and resolveUrl
Expose the XHR and URL resolution utility methods on videojs.hls so they can be shared between the playlist loader and the core plugin. Narrow the scope of the settings variable to be correctly tied to a single instance of the plugin.
Showing
2 changed files
with
29 additions
and
114 deletions
... | @@ -5,102 +5,8 @@ | ... | @@ -5,102 +5,8 @@ |
5 | (function(window, videojs) { | 5 | (function(window, videojs) { |
6 | 'use strict'; | 6 | 'use strict'; |
7 | var | 7 | var |
8 | 8 | resolveUrl = videojs.hls.resolveUrl, | |
9 | /* XXX COPIED REMOVE ME */ | 9 | xhr = videojs.hls.xhr, |
10 | /** | ||
11 | * Constructs a new URI by interpreting a path relative to another | ||
12 | * URI. | ||
13 | * @param basePath {string} a relative or absolute URI | ||
14 | * @param path {string} a path part to combine with the base | ||
15 | * @return {string} a URI that is equivalent to composing `base` | ||
16 | * with `path` | ||
17 | * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue | ||
18 | */ | ||
19 | resolveUrl = function(basePath, path) { | ||
20 | // use the base element to get the browser to handle URI resolution | ||
21 | var | ||
22 | oldBase = document.querySelector('base'), | ||
23 | docHead = document.querySelector('head'), | ||
24 | a = document.createElement('a'), | ||
25 | base = oldBase, | ||
26 | oldHref, | ||
27 | result; | ||
28 | |||
29 | // prep the document | ||
30 | if (oldBase) { | ||
31 | oldHref = oldBase.href; | ||
32 | } else { | ||
33 | base = docHead.appendChild(document.createElement('base')); | ||
34 | } | ||
35 | |||
36 | base.href = basePath; | ||
37 | a.href = path; | ||
38 | result = a.href; | ||
39 | |||
40 | // clean up | ||
41 | if (oldBase) { | ||
42 | oldBase.href = oldHref; | ||
43 | } else { | ||
44 | docHead.removeChild(base); | ||
45 | } | ||
46 | return result; | ||
47 | }, | ||
48 | |||
49 | /* XXX COPIED REMOVE ME */ | ||
50 | /** | ||
51 | * Creates and sends an XMLHttpRequest. | ||
52 | * @param options {string | object} if this argument is a string, it | ||
53 | * is intrepreted as a URL and a simple GET request is | ||
54 | * inititated. If it is an object, it should contain a `url` | ||
55 | * property that indicates the URL to request and optionally a | ||
56 | * `method` which is the type of HTTP request to send. | ||
57 | * @param callback (optional) {function} a function to call when the | ||
58 | * request completes. If the request was not successful, the first | ||
59 | * argument will be falsey. | ||
60 | * @return {object} the XMLHttpRequest that was initiated. | ||
61 | */ | ||
62 | xhr = function(url, callback) { | ||
63 | var | ||
64 | options = { | ||
65 | method: 'GET' | ||
66 | }, | ||
67 | request; | ||
68 | |||
69 | if (typeof callback !== 'function') { | ||
70 | callback = function() {}; | ||
71 | } | ||
72 | |||
73 | if (typeof url === 'object') { | ||
74 | options = videojs.util.mergeOptions(options, url); | ||
75 | url = options.url; | ||
76 | } | ||
77 | |||
78 | request = new window.XMLHttpRequest(); | ||
79 | request.open(options.method, url); | ||
80 | |||
81 | if (options.responseType) { | ||
82 | request.responseType = options.responseType; | ||
83 | } | ||
84 | if (options.withCredentials) { | ||
85 | request.withCredentials = true; | ||
86 | } | ||
87 | |||
88 | request.onreadystatechange = function() { | ||
89 | // wait until the request completes | ||
90 | if (this.readyState !== 4) { | ||
91 | return; | ||
92 | } | ||
93 | |||
94 | // request error | ||
95 | if (this.status >= 400 || this.status === 0) { | ||
96 | return callback.call(this, true, url); | ||
97 | } | ||
98 | |||
99 | return callback.call(this, false, url); | ||
100 | }; | ||
101 | request.send(null); | ||
102 | return request; | ||
103 | }, | ||
104 | 10 | ||
105 | /** | 11 | /** |
106 | * Returns a new master playlist that is the result of merging an | 12 | * Returns a new master playlist that is the result of merging an |
... | @@ -147,7 +53,7 @@ | ... | @@ -147,7 +53,7 @@ |
147 | media, | 53 | media, |
148 | request, | 54 | request, |
149 | 55 | ||
150 | haveMetadata = function(error, url) { | 56 | haveMetadata = function(error, xhr, url) { |
151 | var parser, refreshDelay, update; | 57 | var parser, refreshDelay, update; |
152 | 58 | ||
153 | // any in-flight request is now finished | 59 | // any in-flight request is now finished |
... | @@ -155,9 +61,9 @@ | ... | @@ -155,9 +61,9 @@ |
155 | 61 | ||
156 | if (error) { | 62 | if (error) { |
157 | loader.error = { | 63 | loader.error = { |
158 | status: this.status, | 64 | status: xhr.status, |
159 | message: 'HLS playlist request error at URL: ' + url, | 65 | message: 'HLS playlist request error at URL: ' + url, |
160 | code: (this.status >= 500) ? 4 : 2 | 66 | code: (xhr.status >= 500) ? 4 : 2 |
161 | }; | 67 | }; |
162 | return loader.trigger('error'); | 68 | return loader.trigger('error'); |
163 | } | 69 | } |
... | @@ -165,7 +71,7 @@ | ... | @@ -165,7 +71,7 @@ |
165 | loader.state = 'HAVE_METADATA'; | 71 | loader.state = 'HAVE_METADATA'; |
166 | 72 | ||
167 | parser = new videojs.m3u8.Parser(); | 73 | parser = new videojs.m3u8.Parser(); |
168 | parser.push(this.responseText); | 74 | parser.push(xhr.responseText); |
169 | parser.manifest.uri = url; | 75 | parser.manifest.uri = url; |
170 | 76 | ||
171 | // merge this playlist into the master | 77 | // merge this playlist into the master |
... | @@ -235,7 +141,7 @@ | ... | @@ -235,7 +141,7 @@ |
235 | 141 | ||
236 | // request the new playlist | 142 | // request the new playlist |
237 | request = xhr(resolveUrl(loader.master.uri, playlist.uri), function(error) { | 143 | request = xhr(resolveUrl(loader.master.uri, playlist.uri), function(error) { |
238 | haveMetadata.call(this, error, playlist.uri); | 144 | haveMetadata(error, this, playlist.uri); |
239 | }); | 145 | }); |
240 | }; | 146 | }; |
241 | 147 | ||
... | @@ -249,7 +155,7 @@ | ... | @@ -249,7 +155,7 @@ |
249 | loader.state = 'HAVE_CURRENT_METADATA'; | 155 | loader.state = 'HAVE_CURRENT_METADATA'; |
250 | request = xhr(resolveUrl(loader.master.uri, loader.media().uri), | 156 | request = xhr(resolveUrl(loader.master.uri, loader.media().uri), |
251 | function(error) { | 157 | function(error) { |
252 | haveMetadata.call(this, error, loader.media().uri); | 158 | haveMetadata(error, this, loader.media().uri); |
253 | }); | 159 | }); |
254 | }); | 160 | }); |
255 | 161 | ||
... | @@ -286,8 +192,8 @@ | ... | @@ -286,8 +192,8 @@ |
286 | request = xhr(resolveUrl(srcUrl, parser.manifest.playlists[0].uri), | 192 | request = xhr(resolveUrl(srcUrl, parser.manifest.playlists[0].uri), |
287 | function(error) { | 193 | function(error) { |
288 | // pass along the URL specified in the master playlist | 194 | // pass along the URL specified in the master playlist |
289 | haveMetadata.call(this, | 195 | haveMetadata(error, |
290 | error, | 196 | this, |
291 | parser.manifest.playlists[0].uri); | 197 | parser.manifest.playlists[0].uri); |
292 | }); | 198 | }); |
293 | return loader.trigger('loadedplaylist'); | 199 | return loader.trigger('loadedplaylist'); |
... | @@ -302,7 +208,7 @@ | ... | @@ -302,7 +208,7 @@ |
302 | }] | 208 | }] |
303 | }; | 209 | }; |
304 | loader.master.playlists[srcUrl] = loader.master.playlists[0]; | 210 | loader.master.playlists[srcUrl] = loader.master.playlists[0]; |
305 | return haveMetadata.call(this, null, srcUrl); | 211 | return haveMetadata(null, this, srcUrl); |
306 | }); | 212 | }); |
307 | }; | 213 | }; |
308 | PlaylistLoader.prototype = new videojs.hls.Stream(); | 214 | PlaylistLoader.prototype = new videojs.hls.Stream(); | ... | ... |
... | @@ -32,8 +32,6 @@ videojs.hls = { | ... | @@ -32,8 +32,6 @@ videojs.hls = { |
32 | 32 | ||
33 | var | 33 | var |
34 | 34 | ||
35 | settings, | ||
36 | |||
37 | // the desired length of video to maintain in the buffer, in seconds | 35 | // the desired length of video to maintain in the buffer, in seconds |
38 | goalBufferLength = 5, | 36 | goalBufferLength = 5, |
39 | 37 | ||
... | @@ -109,7 +107,7 @@ var | ... | @@ -109,7 +107,7 @@ var |
109 | * argument will be falsey. | 107 | * argument will be falsey. |
110 | * @return {object} the XMLHttpRequest that was initiated. | 108 | * @return {object} the XMLHttpRequest that was initiated. |
111 | */ | 109 | */ |
112 | xhr = function(url, callback) { | 110 | xhr = videojs.hls.xhr = function(url, callback) { |
113 | var | 111 | var |
114 | options = { | 112 | options = { |
115 | method: 'GET' | 113 | method: 'GET' |
... | @@ -131,7 +129,7 @@ var | ... | @@ -131,7 +129,7 @@ var |
131 | if (options.responseType) { | 129 | if (options.responseType) { |
132 | request.responseType = options.responseType; | 130 | request.responseType = options.responseType; |
133 | } | 131 | } |
134 | if (settings.withCredentials) { | 132 | if (options.withCredentials) { |
135 | request.withCredentials = true; | 133 | request.withCredentials = true; |
136 | } | 134 | } |
137 | 135 | ||
... | @@ -253,7 +251,7 @@ var | ... | @@ -253,7 +251,7 @@ var |
253 | * with `path` | 251 | * with `path` |
254 | * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue | 252 | * @see http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue |
255 | */ | 253 | */ |
256 | resolveUrl = function(basePath, path) { | 254 | resolveUrl = videojs.hls.resolveUrl = function(basePath, path) { |
257 | // use the base element to get the browser to handle URI resolution | 255 | // use the base element to get the browser to handle URI resolution |
258 | var | 256 | var |
259 | oldBase = document.querySelector('base'), | 257 | oldBase = document.querySelector('base'), |
... | @@ -296,6 +294,7 @@ var | ... | @@ -296,6 +294,7 @@ var |
296 | 294 | ||
297 | playlistXhr, | 295 | playlistXhr, |
298 | segmentXhr, | 296 | segmentXhr, |
297 | settings, | ||
299 | loadedPlaylist, | 298 | loadedPlaylist, |
300 | fillBuffer, | 299 | fillBuffer, |
301 | updateCurrentPlaylist, | 300 | updateCurrentPlaylist, |
... | @@ -425,7 +424,10 @@ var | ... | @@ -425,7 +424,10 @@ var |
425 | if (playlistXhr) { | 424 | if (playlistXhr) { |
426 | playlistXhr.abort(); | 425 | playlistXhr.abort(); |
427 | } | 426 | } |
428 | playlistXhr = xhr(resolveUrl(srcUrl, playlist.uri), loadedPlaylist); | 427 | playlistXhr = xhr({ |
428 | url: resolveUrl(srcUrl, playlist.uri), | ||
429 | withCredentials: settings.withCredentials | ||
430 | }, loadedPlaylist); | ||
429 | } else { | 431 | } else { |
430 | player.hls.mediaIndex = | 432 | player.hls.mediaIndex = |
431 | translateMediaIndex(player.hls.mediaIndex, | 433 | translateMediaIndex(player.hls.mediaIndex, |
... | @@ -654,7 +656,8 @@ var | ... | @@ -654,7 +656,8 @@ var |
654 | // request the next segment | 656 | // request the next segment |
655 | segmentXhr = xhr({ | 657 | segmentXhr = xhr({ |
656 | url: segmentUri, | 658 | url: segmentUri, |
657 | responseType: 'arraybuffer' | 659 | responseType: 'arraybuffer', |
660 | withCredentials: settings.withCredentials | ||
658 | }, function(error, url) { | 661 | }, function(error, url) { |
659 | // the segment request is no longer outstanding | 662 | // the segment request is no longer outstanding |
660 | segmentXhr = null; | 663 | segmentXhr = null; |
... | @@ -723,14 +726,20 @@ var | ... | @@ -723,14 +726,20 @@ var |
723 | sourceBuffer.appendBuffer(segmentParser.getFlvHeader()); | 726 | sourceBuffer.appendBuffer(segmentParser.getFlvHeader()); |
724 | 727 | ||
725 | player.hls.mediaIndex = 0; | 728 | player.hls.mediaIndex = 0; |
726 | xhr(srcUrl, function(error, url) { | 729 | xhr({ |
730 | url: srcUrl, | ||
731 | withCredentials: settings.withCredentials | ||
732 | }, function(error, url) { | ||
727 | var uri, parser = new videojs.m3u8.Parser(); | 733 | var uri, parser = new videojs.m3u8.Parser(); |
728 | parser.push(this.responseText); | 734 | parser.push(this.responseText); |
729 | 735 | ||
730 | // master playlists | 736 | // master playlists |
731 | if (parser.manifest.playlists) { | 737 | if (parser.manifest.playlists) { |
732 | player.hls.master = parser.manifest; | 738 | player.hls.master = parser.manifest; |
733 | playlistXhr = xhr(resolveUrl(url, parser.manifest.playlists[0].uri), loadedPlaylist); | 739 | playlistXhr = xhr({ |
740 | url: resolveUrl(url, parser.manifest.playlists[0].uri), | ||
741 | withCredentials: settings.withCredentials | ||
742 | }, loadedPlaylist); | ||
734 | return player.trigger('loadedmanifest'); | 743 | return player.trigger('loadedmanifest'); |
735 | } else { | 744 | } else { |
736 | // infer a master playlist if a media playlist is loaded directly | 745 | // infer a master playlist if a media playlist is loaded directly | ... | ... |
-
Please register or sign in to post a comment