├── README.md ├── data └── hosted.js ├── doc └── main.md ├── jid1-NbC5BaL6G37cRg@jetpack-1.0.0.xpi ├── lib └── main.js ├── package.json └── test └── test-main.js /README.md: -------------------------------------------------------------------------------- 1 | Opens YouTube videos and playlists in mpv, and nukes the crappy YouTube player. 2 | 3 | Installation: 4 | 5 | 1. Be on Linux 6 | 2. Install mpv 7 | 4. Write your youtube creds to ~/.netrc, should look something like the example on the bottom of this file 8 | 5. Install the xpi in this directory 9 | 10 | If you want to hack on this, it's a jetpack add on and works like you'd expect if you know how jetpack add ons work. 11 | 12 | Licensed under the WTFPL. 13 | 14 | machine youtube 15 | login whatever@whatever.com 16 | password hunter2 17 | -------------------------------------------------------------------------------- /data/hosted.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var push = true; 3 | var killOnClose = false; 4 | switch (window.location.host) { 5 | case "youtube.com": 6 | case "www.youtube.com": 7 | if (window.location.pathname == '/watch') { 8 | var player = document.getElementById("player"); 9 | if (player !== null) { 10 | var spacer = document.createElement('div'); 11 | spacer.style.height = "400px"; 12 | player.parentElement.insertBefore(spacer, player); 13 | player.parentElement.removeChild(player); 14 | } 15 | } else { 16 | push = false; 17 | } 18 | break; 19 | case "soundcloud.com": 20 | killOnClose = true; 21 | break; 22 | } 23 | if (push) 24 | self.port.emit("message", { type: "play", host: window.location.host, url: String(window.location.href) }); 25 | 26 | window.addEventListener('unload', function() { 27 | if (killOnClose && push) { 28 | self.port.emit("message", { type: "kill", host: window.location.host, url: String(window.location.href) }); 29 | } 30 | }); 31 | })(); 32 | -------------------------------------------------------------------------------- /doc/main.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddevault/ExternalPlayer/b6aecd012966afc8e95a9ea112ff26a3d064b612/doc/main.md -------------------------------------------------------------------------------- /jid1-NbC5BaL6G37cRg@jetpack-1.0.0.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ddevault/ExternalPlayer/b6aecd012966afc8e95a9ea112ff26a3d064b612/jid1-NbC5BaL6G37cRg@jetpack-1.0.0.xpi -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | const {Cc,Ci} = require("chrome"); 2 | var system = require("sdk/system"); 3 | var syspath; 4 | switch (system.platform.toLowerCase()) { 5 | case "linux": 6 | syspath = system.env.PATH.split(':'); 7 | break; 8 | // TODO: Others, if anyone cares 9 | } 10 | var process = function(file) { 11 | var _ = Cc["@mozilla.org/process/util;1"] 12 | .createInstance(Ci.nsIProcess); 13 | _.init(file); 14 | return _; 15 | } 16 | var file = function(path) { 17 | for (var i = 0; i < syspath.length; i++) { 18 | var _ = Cc["@mozilla.org/file/local;1"] 19 | .createInstance(Ci.nsIFile); 20 | try { 21 | _.initWithPath(syspath[i]); 22 | _.appendRelativePath(path); 23 | if (_.exists() && _.isExecutable()) { 24 | return _; 25 | } 26 | } catch (ex) { 27 | console.log(ex); 28 | } 29 | } 30 | return null; 31 | }; 32 | 33 | let pageMod = require("sdk/page-mod"); 34 | let self = require("sdk/self"); 35 | var lastMessage = new Date(); 36 | var processes = {}; 37 | pageMod.PageMod({ 38 | include: [ 39 | "*.youtube.com" 40 | //"*.soundcloud.com" // TODO: Figure out why kill() doesn't work 41 | ], 42 | contentScriptFile: [ 43 | self.data.url('hosted.js') 44 | ], 45 | onAttach: function(worker) { 46 | worker.port.on("message", function(data) { 47 | if (new Date() - lastMessage < 5000) { 48 | lastMessage = new Date(); 49 | return; 50 | } 51 | if (data.type == "play") { 52 | lastMessage = new Date(); 53 | var f = file("mpv"); 54 | var p = process(f); 55 | p.run(false, [ data.url ], 1); 56 | processes[data.url] = p; 57 | } else if (data.type == "kill") { 58 | if (typeof processes[data.url] !== 'undefined') { 59 | processes[data.url].kill(); 60 | } 61 | } 62 | }); 63 | } 64 | }); 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "externalplayer", 3 | "title": "ExternalPlayer", 4 | "id": "jid1-NbC5BaL6G37cRg@jetpack", 5 | "description": "Play videos for various websites in an external media player.", 6 | "author": "Drew DeVault", 7 | "license": "MIT", 8 | "version": "1.0.0", 9 | "main": "lib/main.js" 10 | } 11 | -------------------------------------------------------------------------------- /test/test-main.js: -------------------------------------------------------------------------------- 1 | var main = require("./main"); 2 | 3 | exports["test main"] = function(assert) { 4 | assert.pass("Unit test running!"); 5 | }; 6 | 7 | exports["test main async"] = function(assert, done) { 8 | assert.pass("async Unit test running!"); 9 | done(); 10 | }; 11 | 12 | require("sdk/test").run(exports); 13 | --------------------------------------------------------------------------------