aboutsummaryrefslogtreecommitdiffstats
path: root/src/js/html5.js
blob: 34f0c391416a78a22bd0135c3b054e0558c00e8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// ==========================================================================
// Plyr HTML5 helpers
// ==========================================================================

import support from './support';
import { removeElement } from './utils/elements';
import { triggerEvent } from './utils/events';
import is from './utils/is';
import { setAspectRatio } from './utils/style';

const html5 = {
    getSources() {
        if (!this.isHTML5) {
            return [];
        }

        const sources = Array.from(this.media.querySelectorAll('source'));

        // Filter out unsupported sources (if type is specified)
        return sources.filter(source => {
            const type = source.getAttribute('type');

            if (is.empty(type)) {
                return true;
            }

            return support.mime.call(this, type);
        });
    },

    // Get quality levels
    getQualityOptions() {
        // Get sizes from <source> elements
        return html5.getSources
            .call(this)
            .map(source => Number(source.getAttribute('size')))
            .filter(Boolean);
    },

    extend() {
        if (!this.isHTML5) {
            return;
        }

        const player = this;

        // Set aspect ratio if set
        setAspectRatio.call(player);

        // Quality
        Object.defineProperty(player.media, 'quality', {
            get() {
                // Get sources
                const sources = html5.getSources.call(player);
                const source = sources.find(source => source.getAttribute('src') === player.source);

                // Return size, if match is found
                return source && Number(source.getAttribute('size'));
            },
            set(input) {
                // Get sources
                const sources = html5.getSources.call(player);

                // Get first match for requested size
                const source = sources.find(source => Number(source.getAttribute('size')) === input);

                // No matching source found
                if (!source) {
                    return;
                }

                // Get current state
                const { currentTime, paused, preload, readyState } = player.media;

                // Set new source
                player.media.src = source.getAttribute('src');

                // Prevent loading if preload="none" and the current source isn't loaded (#1044)
                if (preload !== 'none' || readyState) {
                    // Restore time
                    player.once('loadedmetadata', () => {
                        player.currentTime = currentTime;

                        // Resume playing
                        if (!paused) {
                            player.play();
                        }
                    });

                    // Load new source
                    player.media.load();
                }

                // Trigger change event
                triggerEvent.call(player, player.media, 'qualitychange', false, {
                    quality: input,
                });
            },
        });
    },

    // Cancel current network requests
    // See https://github.com/sampotts/plyr/issues/174
    cancelRequests() {
        if (!this.isHTML5) {
            return;
        }

        // Remove child sources
        removeElement(html5.getSources.call(this));

        // Set blank video src attribute
        // This is to prevent a MEDIA_ERR_SRC_NOT_SUPPORTED error
        // Info: http://stackoverflow.com/questions/32231579/how-to-properly-dispose-of-an-html5-video-and-close-socket-or-connection
        this.media.setAttribute('src', this.config.blankVideo);

        // Load the new empty source
        // This will cancel existing requests
        // See https://github.com/sampotts/plyr/issues/174
        this.media.load();

        // Debugging
        this.debug.log('Cancelled network requests');
    },
};

export default html5;