qutebrowser_view_in_vlc.bash (5066B)
1 #!/usr/bin/env bash 2 # 3 # Behavior: 4 # Userscript for qutebrowser which views the current web page in vlc using 5 # sensible vlc-flags. While viewing the page in MPV, all <video>, <embed>, 6 # and <object> tags in the original page are temporarily removed. Clicking on 7 # such a removed video restores the respective video. 8 # 9 # In order to use this script, just start it using `spawn --userscript` from 10 # qutebrowser. I recommend using an alias, e.g. put this in the 11 # [alias]-section of qutebrowser.conf: 12 # 13 # vlc = spawn --userscript /path/to/view_in_vlc 14 # 15 # Background: 16 # Most of my machines are too slow to play youtube videos using html5, but 17 # they work fine in vlc (and vlc has further advantages like video scaling, 18 # etc). Of course, I don't want the video to be played (or even to be 19 # downloaded) twice — in vlc and in qwebkit. So I often close the tab after 20 # opening it in vlc. However, I actually want to keep the rest of the page 21 # (comments and video suggestions), i.e. only the videos should disappear 22 # when vlc is started. And that's precisely what the present script does. 23 # 24 # Thorsten Wißmann, 2015 (thorsten` on freenode) 25 # Any feedback is welcome! 26 27 set -e 28 29 if [ -z "$QUTE_FIFO" ] ; then 30 cat 1>&2 <<EOF 31 Error: $0 can not be run as a standalone script. 32 33 It is a qutebrowser userscript. In order to use it, call it using 34 'spawn --userscript' as described in qute://help/userscripts.html 35 EOF 36 exit 1 37 fi 38 39 msg() { 40 local cmd="$1" 41 shift 42 local msg="$*" 43 if [ -z "$QUTE_FIFO" ] ; then 44 echo "$cmd: $msg" >&2 45 else 46 echo "message-$cmd '${msg//\'/\\\'}'" >> "$QUTE_FIFO" 47 fi 48 } 49 50 VLC_COMMAND=${VLC_COMMAND:-vlc} 51 # Warning: spaces in single flags are not supported 52 VLC_FLAGS=${VLC_FLAGS:- --qt-minimal-view} 53 IFS=" " read -r -a video_command <<< "$VLC_COMMAND $VLC_FLAGS" 54 55 js() { 56 cat <<EOF 57 58 function descendantOfTagName(child, ancestorTagName) { 59 // tells whether child has some (proper) ancestor 60 // with the tag name ancestorTagName 61 while (child.parentNode != null) { 62 child = child.parentNode; 63 if (typeof child.tagName === 'undefined') break; 64 if (child.tagName.toUpperCase() == ancestorTagName.toUpperCase()) { 65 return true; 66 } 67 } 68 return false; 69 } 70 71 var App = {}; 72 73 var all_videos = []; 74 all_videos.push.apply(all_videos, document.getElementsByTagName("video")); 75 all_videos.push.apply(all_videos, document.getElementsByTagName("object")); 76 all_videos.push.apply(all_videos, document.getElementsByTagName("embed")); 77 App.backup_videos = Array(); 78 App.all_replacements = Array(); 79 for (i = 0; i < all_videos.length; i++) { 80 var video = all_videos[i]; 81 if (descendantOfTagName(video, "object")) { 82 // skip tags that are contained in an object, because we hide 83 // the object anyway. 84 continue; 85 } 86 var replacement = document.createElement("div"); 87 replacement.innerHTML = " 88 <p style=\\"margin-bottom: 0.5em\\"> 89 Opening page with: 90 <span style=\\"font-family: monospace;\\">${video_command[*]}</span> 91 </p> 92 <p> 93 In order to restore this particular video 94 <a style=\\"font-weight: bold; 95 color: white; 96 background: transparent; 97 \\" 98 onClick=\\"restore_video(this, " + i + ");\\" 99 href=\\"javascript: restore_video(this, " + i + ")\\" 100 >click here</a>. 101 </p> 102 "; 103 replacement.style.position = "relative"; 104 replacement.style.zIndex = "100003000000"; 105 replacement.style.fontSize = "1rem"; 106 replacement.style.textAlign = "center"; 107 replacement.style.verticalAlign = "middle"; 108 replacement.style.height = "100%"; 109 replacement.style.background = "#101010"; 110 replacement.style.color = "white"; 111 replacement.style.border = "4px dashed #545454"; 112 replacement.style.padding = "2em"; 113 replacement.style.margin = "auto"; 114 App.all_replacements[i] = replacement; 115 App.backup_videos[i] = video; 116 video.parentNode.replaceChild(replacement, video); 117 } 118 119 function restore_video(obj, index) { 120 obj = App.all_replacements[index]; 121 video = App.backup_videos[index]; 122 console.log(video); 123 obj.parentNode.replaceChild(video, obj); 124 } 125 126 /** force repainting the video, thanks to: 127 * http://martinwolf.org/2014/06/10/force-repaint-of-an-element-with-javascript/ 128 */ 129 var siteHeader = document.getElementById('header'); 130 siteHeader.style.display='none'; 131 siteHeader.offsetHeight; // no need to store this anywhere, the reference is enough 132 siteHeader.style.display='block'; 133 134 EOF 135 } 136 137 printjs() { 138 js | sed 's,//.*$,,' | tr '\n' ' ' 139 } 140 echo "jseval -q $(printjs)" >> "$QUTE_FIFO" 141 142 msg info "Opening $QUTE_URL with vlc" 143 "${video_command[@]}" "$@" "$QUTE_URL"