├── .gitattributes ├── .eslintignore ├── icon128.png ├── icon64.png ├── .gitignore ├── lib ├── isFirefoxPromise.js ├── webExtensionCommands.js ├── hotkeyManager.js ├── content-scripts-register-polyfill.js ├── pageWorkerManager.js ├── browser-polyfill.min.js └── browser-polyfill.min.js.map ├── docs └── img │ ├── Extract_Element.png │ └── Inspect_Element.png ├── .web-extension-id ├── .idea └── watcherTasks.xml ├── data ├── mixcloud.com-view.js ├── pocketcasts.com-view.js ├── tunein.com-view.js ├── di.fm-view.js ├── npr.org-view.js ├── bandcamp.com-view.js ├── hypem.com-view.js ├── soundcloud.com-view.js ├── overcast.fm-view.js ├── radio.yandex.ru-view.js ├── stitcher.com-view.js ├── hulu.com-view.js ├── jango.com-view.js ├── play.pocketcasts.com-view.js ├── play.google.com-view.js ├── cbcmusic.ca-view.js ├── music.yandex.ru-view.js ├── pluralsight.com-view.js ├── netflix.com-view.js ├── plex.tv-view.js ├── udemy.com-view.js ├── player.spotify.com-view.js ├── tidal.com-view.js ├── vk.com-view.js ├── jamstash-view.js ├── kanopy-view.js ├── play.spotify.com-view.js ├── koel-view.js ├── music.apple.com-view.js ├── deezer.com-view.js ├── madsonic-view.js ├── subsonic-view.js ├── pandora.com-view.js ├── music.amazon-view.js ├── open.spotify.com-view.js ├── finder.js ├── w.soundcloud.com-orchestrator.js ├── youtube.com-orchestrator-pageScript.js ├── youtube.com-orchestrator.js └── orchestrator.js ├── .vscode ├── settings.json ├── tasks.json └── launch.json ├── tests ├── play.spotify.com.html ├── player.spotify.com.html ├── madsonic.html ├── youtube.com.html ├── incomplete test-pageworkerManager.js ├── test-main.js ├── pocketcasts.com.html ├── pandora.com.html ├── youtube.com.js ├── main.player.spotify.com.html ├── tidal.com.html ├── main.play.spotify.com.html ├── open.spotify.com.html ├── madsonic-playQueue.html ├── test-youtube-orchestrator.js └── test-orchestrator.js ├── index.html ├── options ├── UserOptions.js ├── options_ui.js ├── Options.js ├── CommandOptions.js ├── ContentScriptOptions.js ├── options_ui.html └── extension.css ├── jsconfig.json ├── .azure-pipelines.yml ├── .eslintrc.json ├── index.js ├── BrowserMediaPlayers.pem ├── package.json ├── README.md ├── manifest.json └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | *.png filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | tests/** 2 | web-ext-artifacts/** 3 | node_modules/** 4 | -------------------------------------------------------------------------------- /icon128.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:14238f687673bddb87fa8060ab39104cea860babcc9da3ef9ccf313a88ff8fd6 3 | size 22435 4 | -------------------------------------------------------------------------------- /icon64.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6cc771805978b08ebe898ac77ed70a48d8aad2f469b84187b2a20ab3316e19d 3 | size 5930 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | *.xpi 3 | icon.png 4 | .idea/ 5 | node_modules 6 | *.log 7 | *.zip 8 | web-ext-artifacts/** 9 | icon425.png 10 | -------------------------------------------------------------------------------- /lib/isFirefoxPromise.js: -------------------------------------------------------------------------------- 1 | export default browser.runtime.getBrowserInfo ? browser.runtime.getBrowserInfo().then(({name}) => name == 'Firefox') : Promise.resolve(false); -------------------------------------------------------------------------------- /docs/img/Extract_Element.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a68bae8f48474a38cf77be92f0b23276e2ed187f2a8350f4b4e3e95d7cc14660 3 | size 416288 4 | -------------------------------------------------------------------------------- /docs/img/Inspect_Element.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:daec59d72d592f84cd0d56d09d315ae176a98cf8a17c16991dd163061da3f4c7 3 | size 624338 4 | -------------------------------------------------------------------------------- /.web-extension-id: -------------------------------------------------------------------------------- 1 | # This file was created by https://github.com/mozilla/web-ext 2 | # Your auto-generated extension ID for addons.mozilla.org is: 3 | jid1-4GP7z3tkUd3Tzg@jetpack -------------------------------------------------------------------------------- /.idea/watcherTasks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /data/mixcloud.com-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'div.player-control'; 7 | MediaKeys.pauseButton = 'div.player-control.pause-state'; 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "json.schemas": [ 3 | { 4 | "fileMatch": [ 5 | "/manifest.json" 6 | ], 7 | "url": "http://json.schemastore.org/webextension" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /data/pocketcasts.com-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'div.play_pause_button.play_button'; 7 | MediaKeys.pauseButton = 'div.play_pause_button.pause_button'; 8 | -------------------------------------------------------------------------------- /data/tunein.com-view.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * MediaKeys namespace. 4 | */ 5 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 6 | 7 | MediaKeys.playButton = 'div.playbutton:not([style*="none"])'; 8 | MediaKeys.pauseButton = 'div.playbutton:not([style*="none"])'; 9 | -------------------------------------------------------------------------------- /tests/play.spotify.com.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spotify 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/player.spotify.com.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spotify 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /data/di.fm-view.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * MediaKeys namespace. 4 | */ 5 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 6 | 7 | var baseXpath = 'div.controls '; 8 | MediaKeys.playButton = baseXpath + 'a.icon-play'; 9 | MediaKeys.pauseButton = baseXpath + 'a.icon-pause'; 10 | -------------------------------------------------------------------------------- /data/npr.org-view.js: -------------------------------------------------------------------------------- 1 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 2 | 3 | MediaKeys.player = '.npr-player'; 4 | MediaKeys.playButton = '.icn-play'; 5 | MediaKeys.pauseButton = '.icn-pause'; 6 | MediaKeys.nextButton = 'player-skip'; 7 | MediaKeys.previousButton = 'player-previous' 8 | -------------------------------------------------------------------------------- /data/bandcamp.com-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'div.playbutton'; 7 | MediaKeys.pauseButton = 'div.playbutton.playing'; 8 | MediaKeys.skipButton = 'div.nextbutton'; 9 | MediaKeys.previousButton = 'div.prevbutton'; -------------------------------------------------------------------------------- /data/hypem.com-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'a#playerPlay'; 7 | MediaKeys.pauseButton = 'a#playerPlay'; 8 | MediaKeys.skipButton = 'a#playerNext'; 9 | MediaKeys.previousButton = 'a#playerPrev'; 10 | -------------------------------------------------------------------------------- /data/soundcloud.com-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'button.playControl'; 7 | MediaKeys.pauseButton = 'button.playing'; 8 | MediaKeys.skipButton = 'button.next'; 9 | MediaKeys.previousButton = 'button.previous'; -------------------------------------------------------------------------------- /data/overcast.fm-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'a#playpausebutton'; 7 | MediaKeys.pauseButton = 'a#playpausebutton'; 8 | MediaKeys.skipButton = 'a#seekforwardbutton'; 9 | MediaKeys.previousButton = 'a#seekbackbutton'; -------------------------------------------------------------------------------- /data/radio.yandex.ru-view.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MediaKeys namespace. 3 | */ 4 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 5 | 6 | MediaKeys.playButton = 'div.player-controls__play'; 7 | MediaKeys.pauseButton = 'div.player-controls__play'; 8 | MediaKeys.skipButton = 'div.slider__item_track:nth-of-type(4) button'; 9 | -------------------------------------------------------------------------------- /data/stitcher.com-view.js: -------------------------------------------------------------------------------- 1 | if (typeof MediaKeys == 'undefined') var MediaKeys = {}; 2 | 3 | MediaKeys.playButton = 'div:not(.playing) > div#player-container-wrapper a#audio_player-play'; 4 | MediaKeys.pauseButton = 'div.playing > div#player-container-wrapper #audio_player-play'; 5 | MediaKeys.skipButton = '#audio_player-skip'; -------------------------------------------------------------------------------- /tests/madsonic.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Madsonic Player 6 | 7 | 8 |