summaryrefslogtreecommitdiff
path: root/misc/userscripts/view_in_mpv
blob: 4ab37d6171ac501e9fba62836c8cd2793fb774d8 (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/env bash
#
# Behavior:
#   Userscript for qutebrowser which views the current web page in mpv using
#   sensible mpv-flags. While viewing the page in MPV, all <video>, <embed>,
#   and <object> tags in the original page are temporarily removed. Clicking on
#   such a removed video restores the respective video.
#
#   In order to use this script, just start it using `spawn --userscript` from
#   qutebrowser. I recommend using an alias, e.g. put this in the
#   [alias]-section of qutebrowser.conf:
#
#     mpv = spawn --userscript /path/to/view_in_mpv
#
# Background:
#   Most of my machines are too slow to play youtube videos using html5, but
#   they work fine in mpv (and mpv has further advantages like video scaling,
#   etc). Of course, I don't want the video to be played (or even to be
#   downloaded) twice — in MPV and in qwebkit. So I often close the tab after
#   opening it in mpv. However, I actually want to keep the rest of the page
#   (comments and video suggestions), i.e. only the videos should disappear
#   when mpv is started. And that's precisely what the present script does.
#
# Thorsten Wißmann, 2015 (thorsten` on freenode)
# Any feedback is welcome!

set -e

if [ -z "$QUTE_FIFO" ] ; then
    cat 1>&2 <<EOF
Error: $0 can not be run as a standalone script.

It is a qutebrowser userscript. In order to use it, call it using
'spawn --userscript' as described in qute://help/userscripts.html
EOF
    exit 1
fi

msg() {
    local cmd="$1"
    shift
    local msg="$*"
    if [ -z "$QUTE_FIFO" ] ; then
        echo "$cmd: $msg" >&2
    else
        echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO"
    fi
}

MPV_COMMAND=${MPV_COMMAND:-mpv}
# Warning: spaces in single flags are not supported
MPV_FLAGS=${MPV_FLAGS:- --force-window --no-terminal --keep-open=yes --ytdl}
IFS=" " read -r -a video_command <<< "$MPV_COMMAND $MPV_FLAGS"

js() {
cat <<EOF

    function descendantOfTagName(child, ancestorTagName) {
        // tells whether child has some (proper) ancestor
        // with the tag name ancestorTagName
        while (child.parentNode != null) {
            child = child.parentNode;
            if (typeof child.tagName === 'undefined') break;
            if (child.tagName.toUpperCase() == ancestorTagName.toUpperCase()) {
                return true;
            }
        }
        return false;
    }

    var App = {};

    var all_videos = [];
    all_videos.push.apply(all_videos, document.getElementsByTagName("video"));
    all_videos.push.apply(all_videos, document.getElementsByTagName("object"));
    all_videos.push.apply(all_videos, document.getElementsByTagName("embed"));
    App.backup_videos = Array();
    App.all_replacements = Array();
    for (i = 0; i < all_videos.length; i++) {
        var video = all_videos[i];
        if (descendantOfTagName(video, "object")) {
            // skip tags that are contained in an object, because we hide
            // the object anyway.
            continue;
        }
        var replacement = document.createElement("div");
        replacement.innerHTML = "
            <p style=\\"margin-bottom: 0.5em\\">
            Opening page with:
            <span style=\\"font-family: monospace;\\">${video_command[*]}</span>
            </p>
            <p>
            In order to restore this particular video
            <a style=\\"font-weight: bold;
                        color: white;
                        background: transparent;
                     \\"
               onClick=\\"restore_video(this, " + i + ");\\"
               href=\\"javascript: restore_video(this, " + i + ")\\"
              >click here</a>.
            </p>
        ";
        replacement.style.position = "relative";
        replacement.style.zIndex = "100003000000";
        replacement.style.fontSize = "1rem";
        replacement.style.textAlign = "center";
        replacement.style.verticalAlign = "middle";
        replacement.style.height = "100%";
        replacement.style.background = "#101010";
        replacement.style.color = "white";
        replacement.style.border = "4px dashed #545454";
        replacement.style.padding = "2em";
        replacement.style.margin = "auto";
        App.all_replacements[i] = replacement;
        App.backup_videos[i] = video;
        video.parentNode.replaceChild(replacement, video);
    }

    function restore_video(obj, index) {
        obj = App.all_replacements[index];
        video = App.backup_videos[index];
        console.log(video);
        obj.parentNode.replaceChild(video, obj);
    }

    /** force repainting the video, thanks to:
     * http://web.archive.org/web/20151029064649/https://martinwolf.org/2014/06/10/force-repaint-of-an-element-with-javascript/
     */
    var siteHeader = document.getElementById('header');
    siteHeader.style.display='none';
    siteHeader.offsetHeight; // no need to store this anywhere, the reference is enough
    siteHeader.style.display='block';

EOF
}

printjs() {
    js | sed 's,//.*$,,' | tr '\n' ' '
}
echo "jseval -q $(printjs)" >> "$QUTE_FIFO"

msg info "Opening $QUTE_URL with mpv"
"${video_command[@]}" "$@" "$QUTE_URL"