videojs 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/lib/videojs.rb +4 -0
- data/lib/videojs/engine.rb +4 -0
- data/lib/videojs/version.rb +3 -0
- data/vendor/assets/fonts/vjs.eot +0 -0
- data/vendor/assets/fonts/vjs.svg +65 -0
- data/vendor/assets/fonts/vjs.ttf +0 -0
- data/vendor/assets/fonts/vjs.woff +0 -0
- data/vendor/assets/javascripts/video-js-resolutions.js +432 -0
- data/vendor/assets/javascripts/video-js.swf +0 -0
- data/vendor/assets/javascripts/video-quality-selector.js +349 -0
- data/vendor/assets/javascripts/video.dev.js +7106 -0
- data/vendor/assets/javascripts/video.js +121 -0
- data/vendor/assets/stylesheets/button-styles.css +24 -0
- data/vendor/assets/stylesheets/video-js-resolutions.css.scss +3 -0
- data/vendor/assets/stylesheets/video-js.css.scss +768 -0
- data/vendor/assets/stylesheets/video-js.min.css +5 -0
- data/vendor/assets/stylesheets/video-js.swf +0 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d48a634490554059c4ec9ffd3299da1f6f1a0e10
|
4
|
+
data.tar.gz: 4019947bedc5c89290e9b819d06feab677c3271a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63984d251c9ea2a11e3293fdf099cc32c4bb9714f0b7b0ab42563db14362005218a80e7396d539c7b2ccd4dfb1c3761765a98525d02454f1e9a0c224a16ea136
|
7
|
+
data.tar.gz: 5dbcd9f78ddc4dbeacd3c35b87ecc5f6cbf88c6edd3664cb7e1bbe898592124ba28324da8abf483afff15f533bbdd03c39c8243813b63414606b93fd34f574b5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 JiriKolarik
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Videojs
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'videojs'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install videojs
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/lib/videojs.rb
ADDED
Binary file
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<?xml version="1.0" standalone="no"?>
|
2
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
4
|
+
<metadata>
|
5
|
+
This is a custom SVG font generated by IcoMoon.
|
6
|
+
<iconset grid="16"></iconset>
|
7
|
+
</metadata>
|
8
|
+
<defs>
|
9
|
+
<font id="VideoJS" horiz-adv-x="512" >
|
10
|
+
<font-face units-per-em="512" ascent="480" descent="-32" />
|
11
|
+
<missing-glyph horiz-adv-x="512" />
|
12
|
+
<glyph class="hidden" unicode="" d="M0,480L 512 -32L0 -32 z" horiz-adv-x="0" />
|
13
|
+
<glyph unicode="" d="M 64,416L 224,416L 224,32L 64,32zM 288,416L 448,416L 448,32L 288,32z" />
|
14
|
+
<glyph unicode="" d="M 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
|
15
|
+
<glyph unicode="" d="M 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
|
16
|
+
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
|
17
|
+
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
|
18
|
+
<glyph unicode="" d="M 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
|
19
|
+
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
|
20
|
+
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
|
21
|
+
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
|
22
|
+
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" />
|
23
|
+
<glyph unicode="" d="M 445.020,18.98c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.373-9.372,24.568,0,33.941
|
24
|
+
C 471.868,103.771, 496.001,162.030, 496.001,224c0,61.969-24.133,120.229-67.952,164.049c-9.372,9.373-9.372,24.569,0,33.941
|
25
|
+
c 9.372,9.372, 24.569,9.372, 33.941,0c 52.885-52.886, 82.011-123.2, 82.011-197.99c0-74.791-29.126-145.104-82.011-197.99
|
26
|
+
C 457.304,21.323, 451.162,18.98, 445.020,18.98zM 359.765,64.235c-6.143,0-12.284,2.343-16.971,7.029c-9.372,9.372-9.372,24.568,0,33.941
|
27
|
+
c 65.503,65.503, 65.503,172.085,0,237.588c-9.372,9.373-9.372,24.569,0,33.941c 9.372,9.371, 24.569,9.372, 33.941,0
|
28
|
+
C 417.532,335.938, 440,281.696, 440,224c0-57.695-22.468-111.938-63.265-152.735C 372.049,66.578, 365.907,64.235, 359.765,64.235zM 274.51,109.49c-6.143,0-12.284,2.343-16.971,7.029c-9.373,9.373-9.373,24.568,0,33.941
|
29
|
+
c 40.55,40.55, 40.55,106.529,0,147.078c-9.373,9.373-9.373,24.569,0,33.941c 9.373,9.372, 24.568,9.372, 33.941,0
|
30
|
+
c 59.265-59.265, 59.265-155.696,0-214.961C 286.794,111.833, 280.652,109.49, 274.51,109.49zM 200.666,440.666 C 213.5,453.5 224,449.15 224,431 L 224,17 C 224-1.15 213.5-5.499 200.666,7.335 L 80,128 L 0,128 L 0,320 L 80,320 L 200.666,440.666 Z" horiz-adv-x="544" />
|
31
|
+
<glyph unicode="" d="M 256,480L 96,224L 256-32L 416,224 z" />
|
32
|
+
<glyph unicode="" d="M 0,480 L 687.158,480 L 687.158-35.207 L 0-35.207 L 0,480 z M 622.731,224.638 C 621.878,314.664 618.46,353.922 597.131,381.656 C 593.291,387.629 586.038,391.042 580.065,395.304 C 559.158,410.669 460.593,416.211 346.247,416.211 C 231.896,416.211 128.642,410.669 108.162,395.304 C 101.762,391.042 94.504,387.629 90.242,381.656 C 69.331,353.922 66.349,314.664 65.069,224.638 C 66.349,134.607 69.331,95.353 90.242,67.62 C 94.504,61.22 101.762,58.233 108.162,53.967 C 128.642,38.18 231.896,33.060 346.247,32.207 C 460.593,33.060 559.158,38.18 580.065,53.967 C 586.038,58.233 593.291,61.22 597.131,67.62 C 618.46,95.353 621.878,134.607 622.731,224.638 z M 331.179,247.952 C 325.389,318.401 287.924,359.905 220.901,359.905 C 159.672,359.905 111.54,304.689 111.54,215.965 C 111.54,126.859 155.405,71.267 227.907,71.267 C 285.79,71.267 326.306,113.916 332.701,184.742 L 263.55,184.742 C 260.81,158.468 249.843,138.285 226.69,138.285 C 190.136,138.285 183.435,174.462 183.435,212.92 C 183.435,265.854 198.665,292.886 223.951,292.886 C 246.492,292.886 260.81,276.511 262.939,247.952 L 331.179,247.952 z M 570.013,247.952 C 564.228,318.401 526.758,359.905 459.74,359.905 C 398.507,359.905 350.379,304.689 350.379,215.965 C 350.379,126.859 394.244,71.267 466.746,71.267 C 524.625,71.267 565.14,113.916 571.536,184.742 L 502.384,184.742 C 499.649,158.468 488.682,138.285 465.529,138.285 C 428.971,138.285 422.27,174.462 422.27,212.92 C 422.27,265.854 437.504,292.886 462.785,292.886 C 485.327,292.886 499.649,276.511 501.778,247.952 L 570.013,247.952 z " horiz-adv-x="687.158" />
|
33
|
+
<glyph unicode="" d="M 64,416L 448,416L 448,32L 64,32z" />
|
34
|
+
<glyph unicode="" d="M 192,416A64,64 12780 1 1 320,416A64,64 12780 1 1 192,416zM 327.765,359.765A64,64 12780 1 1 455.765,359.765A64,64 12780 1 1 327.765,359.765zM 416,224A32,32 12780 1 1 480,224A32,32 12780 1 1 416,224zM 359.765,88.235A32,32 12780 1 1 423.765,88.23500000000001A32,32 12780 1 1 359.765,88.23500000000001zM 224.001,32A32,32 12780 1 1 288.001,32A32,32 12780 1 1 224.001,32zM 88.236,88.235A32,32 12780 1 1 152.236,88.23500000000001A32,32 12780 1 1 88.236,88.23500000000001zM 72.236,359.765A48,48 12780 1 1 168.236,359.765A48,48 12780 1 1 72.236,359.765zM 28,224A36,36 12780 1 1 100,224A36,36 12780 1 1 28,224z" />
|
35
|
+
<glyph unicode="" d="M 224,192 L 224-16 L 144,64 L 48-32 L 0,16 L 96,112 L 16,192 ZM 512,432 L 416,336 L 496,256 L 288,256 L 288,464 L 368,384 L 464,480 Z" />
|
36
|
+
<glyph unicode="" d="M 256,448 C 397.385,448 512,354.875 512,240 C 512,125.124 397.385,32 256,32 C 242.422,32 229.095,32.867 216.088,34.522 C 161.099-20.467 95.463-30.328 32-31.776 L 32-18.318 C 66.268-1.529 96,29.052 96,64 C 96,68.877 95.621,73.665 94.918,78.348 C 37.020,116.48 0,174.725 0,240 C 0,354.875 114.615,448 256,448 Z" />
|
37
|
+
<glyph unicode="" d="M 256,480C 114.615,480,0,365.385,0,224s 114.615-256, 256-256s 256,114.615, 256,256S 397.385,480, 256,480z M 256,352
|
38
|
+
c 70.692,0, 128-57.308, 128-128s-57.308-128-128-128s-128,57.308-128,128S 185.308,352, 256,352z M 408.735,71.265
|
39
|
+
C 367.938,30.468, 313.695,8, 256,8c-57.696,0-111.938,22.468-152.735,63.265C 62.468,112.062, 40,166.304, 40,224
|
40
|
+
c0,57.695, 22.468,111.938, 63.265,152.735l 33.941-33.941c0,0,0,0,0,0c-65.503-65.503-65.503-172.085,0-237.588
|
41
|
+
C 168.937,73.475, 211.125,56, 256,56c 44.874,0, 87.062,17.475, 118.794,49.206c 65.503,65.503, 65.503,172.084,0,237.588l 33.941,33.941
|
42
|
+
C 449.532,335.938, 472,281.695, 472,224C 472,166.304, 449.532,112.062, 408.735,71.265z" />
|
43
|
+
<glyph unicode="" d="M 512,224c-0.639,33.431-7.892,66.758-21.288,97.231c-13.352,30.5-32.731,58.129-56.521,80.96
|
44
|
+
c-23.776,22.848-51.972,40.91-82.492,52.826C 321.197,466.979, 288.401,472.693, 256,472c-32.405-0.641-64.666-7.687-94.167-20.678
|
45
|
+
c-29.524-12.948-56.271-31.735-78.367-54.788c-22.112-23.041-39.58-50.354-51.093-79.899C 20.816,287.104, 15.309,255.375, 16,224
|
46
|
+
c 0.643-31.38, 7.482-62.574, 20.067-91.103c 12.544-28.55, 30.738-54.414, 53.055-75.774c 22.305-21.377, 48.736-38.252, 77.307-49.36
|
47
|
+
C 194.988-3.389, 225.652-8.688, 256-8c 30.354,0.645, 60.481,7.277, 88.038,19.457c 27.575,12.141, 52.558,29.74, 73.183,51.322
|
48
|
+
c 20.641,21.57, 36.922,47.118, 47.627,74.715c 6.517,16.729, 10.94,34.2, 13.271,51.899c 0.623-0.036, 1.249-0.060, 1.881-0.060
|
49
|
+
c 17.673,0, 32,14.326, 32,32c0,0.898-0.047,1.786-0.119,2.666L 512,223.999 z M 461.153,139.026c-11.736-26.601-28.742-50.7-49.589-70.59
|
50
|
+
c-20.835-19.905-45.5-35.593-72.122-45.895C 312.828,12.202, 284.297,7.315, 256,8c-28.302,0.649-56.298,6.868-81.91,18.237
|
51
|
+
c-25.625,11.333-48.842,27.745-67.997,47.856c-19.169,20.099-34.264,43.882-44.161,69.529C 51.997,169.264, 47.318,196.729, 48,224
|
52
|
+
c 0.651,27.276, 6.664,54.206, 17.627,78.845c 10.929,24.65, 26.749,46.985, 46.123,65.405c 19.365,18.434, 42.265,32.935, 66.937,42.428
|
53
|
+
C 203.356,420.208, 229.755,424.681, 256,424c 26.25-0.653, 52.114-6.459, 75.781-17.017c 23.676-10.525, 45.128-25.751, 62.812-44.391
|
54
|
+
c 17.698-18.629, 31.605-40.647, 40.695-64.344C 444.412,274.552, 448.679,249.219, 448,224l 0.119,0 c-0.072-0.88-0.119-1.768-0.119-2.666
|
55
|
+
c0-16.506, 12.496-30.087, 28.543-31.812C 473.431,172.111, 468.278,155.113, 461.153,139.026z" />
|
56
|
+
<glyph unicode="" d="M 256,480 C 116.626,480 3.271,368.619 0.076,230.013 C 3.036,350.945 94.992,448 208,448 C 322.875,448 416,347.712 416,224 C 416,197.49 437.49,176 464,176 C 490.51,176 512,197.49 512,224 C 512,365.385 397.385,480 256,480 ZM 256-32 C 395.374-32 508.729,79.381 511.924,217.987 C 508.964,97.055 417.008,0 304,0 C 189.125,0 96,100.288 96,224 C 96,250.51 74.51,272 48,272 C 21.49,272 0,250.51 0,224 C 0,82.615 114.615-32 256-32 Z" />
|
57
|
+
<glyph unicode="" d="M 432,128c-22.58,0-42.96-9.369-57.506-24.415L 158.992,211.336C 159.649,215.462, 160,219.689, 160,224
|
58
|
+
s-0.351,8.538-1.008,12.663l 215.502,107.751C 389.040,329.369, 409.42,320, 432,320c 44.183,0, 80,35.817, 80,80S 476.183,480, 432,480
|
59
|
+
s-80-35.817-80-80c0-4.311, 0.352-8.538, 1.008-12.663L 137.506,279.585C 122.96,294.63, 102.58,304, 80,304c-44.183,0-80-35.818-80-80
|
60
|
+
c0-44.184, 35.817-80, 80-80c 22.58,0, 42.96,9.369, 57.506,24.414l 215.502-107.751C 352.352,56.538, 352,52.311, 352,48
|
61
|
+
c0-44.184, 35.817-80, 80-80s 80,35.816, 80,80C 512,92.182, 476.183,128, 432,128z" />
|
62
|
+
<glyph unicode="" d="M 96,416L 416,224L 96,32 z" />
|
63
|
+
<glyph unicode="" d="M 512,480 L 512,272 L 432,352 L 336,256 L 288,304 L 384,400 L 304,480 ZM 224,144 L 128,48 L 208-32 L 0-32 L 0,176 L 80,96 L 176,192 Z" />
|
64
|
+
<glyph unicode=" " horiz-adv-x="256" />
|
65
|
+
</font></defs></svg>
|
Binary file
|
Binary file
|
@@ -0,0 +1,432 @@
|
|
1
|
+
// Resolution switching support for videojs
|
2
|
+
//
|
3
|
+
// In this plugin I'm really going out of my way to *not* override the
|
4
|
+
// core videojs namespace and to *not* change the core API. As a
|
5
|
+
// result this plugin is not as efficient as it might be. It
|
6
|
+
// initializes itself *for each player* as scoped variables inside the
|
7
|
+
// plugin closure and grafts itself on to *the instance on which it was
|
8
|
+
// called* rather than on the videojs player prototype. I don't expect
|
9
|
+
// this to be a big deal for anybody.
|
10
|
+
videojs.plugin('resolutions', function(options) {
|
11
|
+
var player = this;
|
12
|
+
|
13
|
+
// 'reduce' utility method
|
14
|
+
// @param {Array} array to iterate over
|
15
|
+
// @param {Function} iterator function for collector
|
16
|
+
// @param {Array|Object|Number|String} initial collector
|
17
|
+
// @return collector
|
18
|
+
vjs.reduce = function(arr, fn, init, n) {
|
19
|
+
if (!arr || arr.length === 0) { return; }
|
20
|
+
for (var i=0,j=arr.length; i<j; i++) {
|
21
|
+
init = fn.call(arr, init, arr[i], i);
|
22
|
+
}
|
23
|
+
return init;
|
24
|
+
};
|
25
|
+
|
26
|
+
this.resolutions_ = {
|
27
|
+
options_: {},
|
28
|
+
|
29
|
+
// takes an existing stream and stops the download entirely
|
30
|
+
// without killing the player or disposing of the tech
|
31
|
+
stopStream: function(){
|
32
|
+
switch(player.techName){
|
33
|
+
case "Html5":
|
34
|
+
break;
|
35
|
+
case "Flash":
|
36
|
+
player.tech.el_.vjs_stop();
|
37
|
+
break;
|
38
|
+
}
|
39
|
+
|
40
|
+
// this may cause flash or the native player to emit errors but
|
41
|
+
// they are harmless
|
42
|
+
player.src("");
|
43
|
+
},
|
44
|
+
|
45
|
+
// it is necessary to remove the sources from the DOM after
|
46
|
+
// parsing them because otherwise the native player may be
|
47
|
+
// inclined to stream both sources
|
48
|
+
removeSources: function(el){
|
49
|
+
var videoEl = player.el_.getElementsByTagName("video")[0];
|
50
|
+
|
51
|
+
if (player.techName !== "Html5" || !videoEl) return;
|
52
|
+
|
53
|
+
var srcs = videoEl.getElementsByTagName("source");
|
54
|
+
for(var i=0;i<srcs.length;i++){
|
55
|
+
videoEl.removeChild(srcs[i]);
|
56
|
+
}
|
57
|
+
},
|
58
|
+
|
59
|
+
// buckets all parsed sources by their type ("video/mp4", for example)
|
60
|
+
// @param {Array} array of sources:
|
61
|
+
// [
|
62
|
+
// {
|
63
|
+
// "data-res": "HD",
|
64
|
+
// "type": "video/mp4",
|
65
|
+
// "src": "http://some_video_url_hd"
|
66
|
+
// },
|
67
|
+
// {
|
68
|
+
// "data-default": "true",
|
69
|
+
// "data-res": "SD",
|
70
|
+
// "type": "video/mp4",
|
71
|
+
// "src": "http://some_video_url_sd"
|
72
|
+
// },
|
73
|
+
// {
|
74
|
+
// "data-default": "true",
|
75
|
+
// "data-res": "SD",
|
76
|
+
// "type": "video/ogv",
|
77
|
+
// "src": "http://some_video_url_sd"
|
78
|
+
// }
|
79
|
+
// ]
|
80
|
+
// @return sources grouped by type:
|
81
|
+
// {
|
82
|
+
// "video/mp4": [
|
83
|
+
// {
|
84
|
+
// "data-res": "HD",
|
85
|
+
// "type": "video/mp4",
|
86
|
+
// "src": "http://some_video_url_hd"
|
87
|
+
// },
|
88
|
+
// {
|
89
|
+
// "data-default": "true",
|
90
|
+
// "data-res": "SD",
|
91
|
+
// "type": "video/mp4",
|
92
|
+
// "src": "http://some_video_url_sd"
|
93
|
+
// }
|
94
|
+
// ]
|
95
|
+
// "video/ogv": [
|
96
|
+
// {
|
97
|
+
// "data-res": "SD",
|
98
|
+
// "type": "video/ogv",
|
99
|
+
// "src": "http://some_video_url_sd"
|
100
|
+
// }
|
101
|
+
// ]
|
102
|
+
// }
|
103
|
+
bucketByTypes: function(sources){
|
104
|
+
return vjs.reduce(sources, function(init, val, i){
|
105
|
+
(init[val.type] = init[val.type] || []).push(val);
|
106
|
+
return init;
|
107
|
+
}, {}, player);
|
108
|
+
},
|
109
|
+
|
110
|
+
// takes parsed sources and selects the most appropriate source
|
111
|
+
// taking into account resolution, technology support, and the
|
112
|
+
// user's previous selections. also indexes the sources
|
113
|
+
// @param {Array} array of sources:
|
114
|
+
// [
|
115
|
+
// {
|
116
|
+
// "data-res": "HD",
|
117
|
+
// "type": "video/mp4",
|
118
|
+
// "src": "http://some_video_url_hd"
|
119
|
+
// },
|
120
|
+
// {
|
121
|
+
// "data-default": "true",
|
122
|
+
// "data-res": "SD",
|
123
|
+
// "type": "video/mp4",
|
124
|
+
// "src": "http://some_video_url_sd"
|
125
|
+
// },
|
126
|
+
// {
|
127
|
+
// "data-default": "true",
|
128
|
+
// "data-res": "SD",
|
129
|
+
// "type": "video/ogv",
|
130
|
+
// "src": "http://some_video_url_sd"
|
131
|
+
// }
|
132
|
+
// ]
|
133
|
+
// @return {Object} single source:
|
134
|
+
// {
|
135
|
+
// "data-res": "HD",
|
136
|
+
// "type": "video/mp4",
|
137
|
+
// "src": "http://some_video_url_jd",
|
138
|
+
// "index": 0
|
139
|
+
// }
|
140
|
+
selectSource: function(sources){
|
141
|
+
this.removeSources();
|
142
|
+
|
143
|
+
var sourcesByType = this.bucketByTypes(sources);
|
144
|
+
var typeAndTech = this.selectTypeAndTech(sources);
|
145
|
+
|
146
|
+
if (!typeAndTech) return false;
|
147
|
+
|
148
|
+
// even though we choose the best resolution for the user here, we
|
149
|
+
// should remember the resolutions so that we can potentially
|
150
|
+
// change resolution later
|
151
|
+
this.options_['sourceResolutions'] = sourcesByType[typeAndTech.type];
|
152
|
+
|
153
|
+
return this.selectResolution(this.options_['sourceResolutions']);
|
154
|
+
},
|
155
|
+
|
156
|
+
// takes parsed sources and returns the most appropriate
|
157
|
+
// technology and video type
|
158
|
+
// @param {Array} array of sources:
|
159
|
+
// [
|
160
|
+
// {
|
161
|
+
// "data-res": "HD",
|
162
|
+
// "type": "video/mp4",
|
163
|
+
// "src": "http://some_video_url_hd"
|
164
|
+
// },
|
165
|
+
// {
|
166
|
+
// "data-default": "true",
|
167
|
+
// "data-res": "SD",
|
168
|
+
// "type": "video/mp4",
|
169
|
+
// "src": "http://some_video_url_sd"
|
170
|
+
// },
|
171
|
+
// {
|
172
|
+
// "data-default": "true",
|
173
|
+
// "data-res": "SD",
|
174
|
+
// "type": "video/ogv",
|
175
|
+
// "src": "http://some_video_url_sd"
|
176
|
+
// }
|
177
|
+
// ]
|
178
|
+
// @return {Object} type/tech:
|
179
|
+
// {
|
180
|
+
// "type": "video/ogv",
|
181
|
+
// "tech": "Html5"
|
182
|
+
// }
|
183
|
+
selectTypeAndTech: function(sources) {
|
184
|
+
var techName;
|
185
|
+
var tech;
|
186
|
+
|
187
|
+
for (var i=0,j=player.options_['techOrder'];i<j.length;i++) {
|
188
|
+
techName = videojs.capitalize(j[i]);
|
189
|
+
tech = window['videojs'][techName];
|
190
|
+
|
191
|
+
// Check if the browser supports this technology
|
192
|
+
if (tech.isSupported()) {
|
193
|
+
// Loop through each source object
|
194
|
+
for (var a=0,b=sources;a<b.length;a++) {
|
195
|
+
var source = b[a];
|
196
|
+
// Check if source can be played with this technology
|
197
|
+
if (tech['canPlaySource'](source)) {
|
198
|
+
return { type: source.type, tech: techName };
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
},
|
204
|
+
|
205
|
+
// takes an array of sources of homogeneous type (ie. a complete
|
206
|
+
// "bucket" from the output of bucketByTypes) and returns the best
|
207
|
+
// source, taking into account the user's previous preferences
|
208
|
+
// stored in local storage
|
209
|
+
// @param {Array} homogeneous sources:
|
210
|
+
// [
|
211
|
+
// {
|
212
|
+
// "data-res": "HD",
|
213
|
+
// "type": "video/mp4",
|
214
|
+
// "src": "http://some_video_url_hd"
|
215
|
+
// },
|
216
|
+
// {
|
217
|
+
// "data-default": "true",
|
218
|
+
// "data-res": "SD",
|
219
|
+
// "type": "video/mp4",
|
220
|
+
// "src": "http://some_video_url_sd"
|
221
|
+
// }
|
222
|
+
// ]
|
223
|
+
// @return {Object} singular best source:
|
224
|
+
// {
|
225
|
+
// "data-default": "true",
|
226
|
+
// "data-res": "SD",
|
227
|
+
// "type": "video/mp4",
|
228
|
+
// "src": "http://some_video_url_sd"
|
229
|
+
// "index": 1
|
230
|
+
// }
|
231
|
+
selectResolution: function(typeSources) {
|
232
|
+
var defaultRes = 0;
|
233
|
+
var supportsLocalStorage = !!window.localStorage;
|
234
|
+
|
235
|
+
// check to see if any sources are marked as default
|
236
|
+
videojs.obj.each(typeSources, function(i, s){
|
237
|
+
// add the index here so we can reference it later
|
238
|
+
s.index = parseInt(i, 10);
|
239
|
+
|
240
|
+
if (s['data-default']) defaultRes = s.index;
|
241
|
+
}, player);
|
242
|
+
|
243
|
+
// if the user has previously selected a preference, check if
|
244
|
+
// that preference is available. if not, use the source marked
|
245
|
+
// default
|
246
|
+
var preferredRes = defaultRes;
|
247
|
+
|
248
|
+
// trying to follow the videojs code conventions of if statements
|
249
|
+
if (supportsLocalStorage){
|
250
|
+
var storedRes = parseInt(window.localStorage.getItem('videojs_preferred_res'), 10);
|
251
|
+
|
252
|
+
if (!isNaN(storedRes))
|
253
|
+
preferredRes = storedRes;
|
254
|
+
}
|
255
|
+
|
256
|
+
var maxRes = (typeSources.length - 1);
|
257
|
+
var actualRes = preferredRes > maxRes ? maxRes : preferredRes;
|
258
|
+
|
259
|
+
return typeSources[actualRes];
|
260
|
+
}
|
261
|
+
};
|
262
|
+
|
263
|
+
// convenience method
|
264
|
+
// @return {String} cached resolution label:
|
265
|
+
// "SD"
|
266
|
+
player.resolution = function(){
|
267
|
+
return this.cache_.src.res;
|
268
|
+
};
|
269
|
+
|
270
|
+
// takes a source and switches the player's stream to it on the fly
|
271
|
+
// @param {Object} singular source:
|
272
|
+
// {
|
273
|
+
// "data-default": "true",
|
274
|
+
// "data-res": "SD",
|
275
|
+
// "type": "video/mp4",
|
276
|
+
// "src": "http://some_video_url_sd"
|
277
|
+
// }
|
278
|
+
player.changeResolution = function(new_source){
|
279
|
+
// has the exact same source been chosen?
|
280
|
+
if (this.cache_.src === new_source.src){
|
281
|
+
this.trigger('resolutionchange');
|
282
|
+
return this; // basically a no-op
|
283
|
+
}
|
284
|
+
|
285
|
+
// remember our position and playback state
|
286
|
+
var curTime = this.currentTime();
|
287
|
+
var remainPaused = this.paused();
|
288
|
+
|
289
|
+
// pause playback
|
290
|
+
this.pause();
|
291
|
+
|
292
|
+
// attempts to stop the download of the existing video
|
293
|
+
this.resolutions_.stopStream();
|
294
|
+
|
295
|
+
// HTML5 tends to not recover from reloading the tech but it can
|
296
|
+
// generally handle changing src. Flash generally cannot handle
|
297
|
+
// changing src but can reload its tech.
|
298
|
+
if (this.techName === "Html5"){
|
299
|
+
this.src(new_source.src);
|
300
|
+
} else {
|
301
|
+
this.loadTech(this.techName, {src: new_source.src});
|
302
|
+
}
|
303
|
+
|
304
|
+
// when the technology is re-started, kick off the new stream
|
305
|
+
this.ready(function() {
|
306
|
+
this.one('loadeddata', vjs.bind(this, function() {
|
307
|
+
this.currentTime(curTime);
|
308
|
+
}));
|
309
|
+
|
310
|
+
this.trigger('resolutionchange');
|
311
|
+
|
312
|
+
if (!remainPaused) {
|
313
|
+
this.load();
|
314
|
+
this.play();
|
315
|
+
}
|
316
|
+
|
317
|
+
// remember this selection
|
318
|
+
vjs.setLocalStorage('videojs_preferred_res', parseInt(new_source.index, 10));
|
319
|
+
});
|
320
|
+
};
|
321
|
+
|
322
|
+
/* Resolution Menu Items
|
323
|
+
================================================================================ */
|
324
|
+
var ResolutionMenuItem = videojs.MenuItem.extend({
|
325
|
+
init: function(player, options){
|
326
|
+
// Modify options for parent MenuItem class's init.
|
327
|
+
options['label'] = options.source['data-res'];
|
328
|
+
videojs.MenuItem.call(this, player, options);
|
329
|
+
|
330
|
+
this.source = options.source;
|
331
|
+
this.resolution = options.source['data-res'];
|
332
|
+
|
333
|
+
this.player_.one('loadstart', vjs.bind(this, this.update));
|
334
|
+
this.player_.on('resolutionchange', vjs.bind(this, this.update));
|
335
|
+
}
|
336
|
+
});
|
337
|
+
|
338
|
+
ResolutionMenuItem.prototype.onClick = function(){
|
339
|
+
videojs.MenuItem.prototype.onClick.call(this);
|
340
|
+
this.player_.changeResolution(this.source);
|
341
|
+
};
|
342
|
+
|
343
|
+
ResolutionMenuItem.prototype.update = function(){
|
344
|
+
var player = this.player_;
|
345
|
+
if ((player.cache_['src'] === this.source.src)) {
|
346
|
+
this.selected(true);
|
347
|
+
} else {
|
348
|
+
this.selected(false);
|
349
|
+
}
|
350
|
+
};
|
351
|
+
|
352
|
+
/* Resolutions Button
|
353
|
+
================================================================================ */
|
354
|
+
var ResolutionButton = videojs.MenuButton.extend({
|
355
|
+
init: function(player, options) {
|
356
|
+
videojs.MenuButton.call(this, player, options);
|
357
|
+
|
358
|
+
if (this.items.length <= 1) {
|
359
|
+
this.hide();
|
360
|
+
}
|
361
|
+
}
|
362
|
+
});
|
363
|
+
|
364
|
+
ResolutionButton.prototype.sourceResolutions_;
|
365
|
+
|
366
|
+
ResolutionButton.prototype.sourceResolutions = function() {
|
367
|
+
return this.sourceResolutions_;
|
368
|
+
};
|
369
|
+
|
370
|
+
ResolutionButton.prototype.onClick = function(e){
|
371
|
+
// Only proceed if the target of the click was a DIV (just the button and its inner div, not the menu)
|
372
|
+
// This prevents the menu from opening and closing when one of the menu items is clicked.
|
373
|
+
if (e.target.className.match(/vjs-control-content/)) {
|
374
|
+
|
375
|
+
// Toggle the 'touched' class
|
376
|
+
this[this.el_.className.match(/touched/) ? "removeClass" : "addClass"]("touched");
|
377
|
+
} else {
|
378
|
+
|
379
|
+
// Remove the 'touched' class from all control bar buttons with menus to hide any already visible...
|
380
|
+
var buttons = document.getElementsByClassName('vjs-menu-button');
|
381
|
+
for(var i=0;i<buttons.length;i++){
|
382
|
+
videojs.removeClass(buttons[i], 'touched');
|
383
|
+
}
|
384
|
+
|
385
|
+
this.removeClass('touched');
|
386
|
+
}
|
387
|
+
};
|
388
|
+
|
389
|
+
ResolutionButton.prototype.createItems = function(){
|
390
|
+
var resolutions = this.sourceResolutions_ = this.player_.resolutions_.options_['sourceResolutions'];
|
391
|
+
var items = [];
|
392
|
+
for (var i = 0; i < resolutions.length; i++) {
|
393
|
+
items.push(new ResolutionMenuItem(this.player_, {
|
394
|
+
'source': this.sourceResolutions_[i]
|
395
|
+
}));
|
396
|
+
}
|
397
|
+
return items;
|
398
|
+
};
|
399
|
+
|
400
|
+
/**
|
401
|
+
* @constructor
|
402
|
+
*/
|
403
|
+
ResolutionsButton = ResolutionButton.extend({
|
404
|
+
/** @constructor */
|
405
|
+
init: function(player, options, ready){
|
406
|
+
ResolutionButton.call(this, player, options, ready);
|
407
|
+
this.el_.setAttribute('aria-label','Resolutions Menu');
|
408
|
+
this.el_.setAttribute('id',"vjs-resolutions-button");
|
409
|
+
}
|
410
|
+
});
|
411
|
+
|
412
|
+
ResolutionsButton.prototype.kind_ = 'resolutions';
|
413
|
+
ResolutionsButton.prototype.buttonText = 'Resolutions';
|
414
|
+
ResolutionsButton.prototype.className = 'vjs-resolutions-button';
|
415
|
+
|
416
|
+
// Add Button to controlBar
|
417
|
+
videojs.obj.merge(player.controlBar.options_['children'], {
|
418
|
+
'resolutionsButton': {}
|
419
|
+
});
|
420
|
+
|
421
|
+
// let's get the party started!
|
422
|
+
// we have to grab the parsed sources and select the source with our
|
423
|
+
// resolution-aware source selector
|
424
|
+
var source = player.resolutions_.selectSource(player.options_['sources']);
|
425
|
+
|
426
|
+
// when the player is ready, add the resolution button to the control bar
|
427
|
+
player.ready(function(){
|
428
|
+
player.changeResolution(source);
|
429
|
+
var button = new ResolutionsButton(player);
|
430
|
+
player.controlBar.addChild(button);
|
431
|
+
});
|
432
|
+
});
|