browser-mpris2
browser-mpris2 copied to clipboard
Add Support for Youtube Music
I can do this but I don't know where url is defined in the code or if there can be multiple urls for a single service
Unfortunately, Youtube Music is not available in my country so I'm afraid I can't do much about this. I can help you though if you have code-related questions.
OK. Where does the scan for URL happen? Is it possible to match multiple URLs?
Look into manifest.json, here's the relevant docs.
Youtube Music support would be cool.
The manifest glob should already match the Music url, which is https://music.youtube.com , so something else might be stopping it. I'll have a deeper look after work.
Good extension BTW, thanks! :)
Ah, all the classes have different names. Many start with the "ytmusic-". So that is going to fool the code that looks for the buttons.
Copy/pasted the HTML from their page below.
The controls are
- .previous-button
- .play-pause-button
- .next-button
- .volume is the mute button
- .volume-slider (or #volume-slider) is the volume control
<ytmusic-player-bar slot="player-bar" class="style-scope ytmusic-app" repeat-mode_="NONE" style="--ytmusic-player-bar-fullscreen-progress-bar-inset:20px;">
<h2 class="player-bar-a11y-label style-scope ytmusic-player-bar">Player bar</h2>
<div id="left-controls" class="left-controls style-scope ytmusic-player-bar" style="width: 292px;">
<div class="left-controls-buttons style-scope ytmusic-player-bar">
<paper-icon-button class="previous-button style-scope ytmusic-player-bar" icon="miniplayer:skip-previous" role="button" tabindex="0" aria-disabled="false" title="Previous song" aria-label="Previous song"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon"><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" class="style-scope iron-icon"></path></g></svg>
</iron-icon><paper-ripple id="ink" center="" class="circle style-scope paper-icon-button">
<div id="background" class="style-scope paper-ripple" style="opacity: 0;"></div>
<div id="waves" class="style-scope paper-ripple"></div>
</paper-ripple></paper-icon-button>
<paper-icon-button id="play-pause-button" class="play-pause-button style-scope ytmusic-player-bar" role="button" tabindex="0" aria-disabled="false" title="Play" aria-label="Play"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon"><path d="M8 5v14l11-7z" class="style-scope iron-icon"></path></g></svg>
</iron-icon><paper-ripple id="ink" center="" class="circle style-scope paper-icon-button">
<div id="background" class="style-scope paper-ripple" style="opacity: 0.00384;"></div>
<div id="waves" class="style-scope paper-ripple"></div>
</paper-ripple></paper-icon-button>
<paper-icon-button class="next-button style-scope ytmusic-player-bar" icon="miniplayer:skip-next" role="button" tabindex="0" aria-disabled="false" title="Next song" aria-label="Next song"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" class="style-scope iron-icon"></path></g></svg>
</iron-icon></paper-icon-button>
</div>
<span class="time-info style-scope ytmusic-player-bar">0:01 / 4:16</span>
</div>
<div class="middle-controls style-scope ytmusic-player-bar">
<img class="image style-scope ytmusic-player-bar" alt="" draggable="false" src="https://i.ytimg.com/vi/SDTZ7iX4vTQ/hq720.jpg?sqp=-oaymwEXCJADEOEBIAQqCwjVARCqCBh4INgESFo&rs=AMzJL3kYvSxVf5GSitXzCYr6UiZ_lyWgAA">
<div class="content-info-wrapper style-scope ytmusic-player-bar">
<yt-formatted-string class="title style-scope ytmusic-player-bar" ellipsis-truncate="" title="Pumped Up Kicks">Pumped Up Kicks</yt-formatted-string>
<span class="byline-wrapper style-scope ytmusic-player-bar">
<div id="badges" class="style-scope ytmusic-player-bar"></div>
<span class="advertisement style-scope ytmusic-player-bar" hidden="">Ad</span>
<span class="subtitle style-scope ytmusic-player-bar">
<yt-formatted-string class="byline style-scope ytmusic-player-bar complex-string" ellipsis-truncate="" title="Foster the People" has-link-only_=""><a class="yt-simple-endpoint style-scope yt-formatted-string" spellcheck="false" href="browse/UCIzEvQ6PlJ9XxeDrT9jEBTA">Foster the People</a></yt-formatted-string>
<yt-formatted-string class="byline style-scope ytmusic-player-bar complex-string" ellipsis-truncate="" title="492M views • 4M likes">492M views • 4M likes</yt-formatted-string>
<template is="dom-repeat" as="text" class="style-scope ytmusic-player-bar"></template>
</span>
</span>
</div>
<div class="middle-controls-buttons style-scope ytmusic-player-bar">
<ytmusic-like-button-renderer id="like-button-renderer" class="thumbs style-scope ytmusic-player-bar" show-hover="" like-status="LIKE">
<paper-icon-button class="dislike style-scope ytmusic-like-button-renderer" role="button" tabindex="0" aria-disabled="false" title="Dislike" aria-label="Dislike" aria-pressed="false"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M14.9 3H6c-.8 0-1.5.5-1.8 1.2l-3 7.3c-.1.2-.2.4-.2.7v2c0 1.1.9 2 2 2h6.3l-1 4.7v.3c0 .4.2.8.4 1.1.6.7 1.5.7 2.1.1l5.5-5.7c.4-.4.6-.9.6-1.4V5c0-1.1-.9-2-2-2zm-.2 12.6l-3.5 3.6c-.2.2-.5 0-.4-.2l1-4.6H4c-.6 0-1-.5-1-1v-1.1l2.7-6.6c.2-.5.6-.7 1-.7H14c.5 0 1 .5 1 1v8.8c-.1.3-.2.6-.3.8zM19 3h4v12h-4V3z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
<paper-icon-button class="like style-scope ytmusic-like-button-renderer" role="button" tabindex="0" aria-disabled="false" title="Like" aria-label="Like" aria-pressed="true"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 10z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
</ytmusic-like-button-renderer>
<ytmusic-menu-renderer class="menu style-scope ytmusic-player-bar">
<div id="top-level-buttons" class="style-scope ytmusic-menu-renderer"></div>
<paper-icon-button id="button" class="dropdown-trigger style-scope ytmusic-menu-renderer" icon="yt-icons:more_vert" role="button" tabindex="0" aria-disabled="false" title="More actions" aria-label="More actions"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon><paper-ripple id="ink" center="" class="circle style-scope paper-icon-button">
<div id="background" class="style-scope paper-ripple" style="opacity: 0.00944;"></div>
<div id="waves" class="style-scope paper-ripple"></div>
</paper-ripple></paper-icon-button>
<template is="dom-if" class="style-scope ytmusic-menu-renderer"></template>
</ytmusic-menu-renderer>
<template is="dom-if" class="style-scope ytmusic-player-bar"></template>
</div>
<paper-icon-button class="toggle-player-page-button style-scope ytmusic-player-bar" icon="yt-icons:arrow-drop-down" role="button" tabindex="0" aria-disabled="false" title="Open player page" aria-label="Open player page"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M7 10l5 5 5-5z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
</div>
<div id="right-controls" class="right-controls style-scope ytmusic-player-bar" style="width: 292px;">
<paper-slider id="volume-slider" class="volume-slider style-scope ytmusic-player-bar" max="100" min="0" step="5" role="slider" tabindex="0" aria-disabled="false" value="100" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" title="Volume" aria-label="Volume"><div id="sliderContainer" class="style-scope paper-slider"><div class="bar-container style-scope paper-slider"><paper-progress id="sliderBar" aria-hidden="true" class="style-scope paper-slider" role="progressbar" value="100" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" aria-disabled="false" style="touch-action: none;">
<div id="progressContainer" class="style-scope paper-progress">
<div id="secondaryProgress" class="style-scope paper-progress" hidden="" style="transform: scaleX(0);"></div>
<div id="primaryProgress" class="style-scope paper-progress" style="transform: scaleX(1);"></div>
</div>
</paper-progress></div><template is="dom-if" class="style-scope paper-slider"></template><div id="sliderKnob" class="slider-knob style-scope paper-slider" style="touch-action: none; left: 100%;"><div class="slider-knob-inner style-scope paper-slider" value="100"></div></div></div><template is="dom-if" class="style-scope paper-slider"></template></paper-slider>
<div class="right-controls-buttons style-scope ytmusic-player-bar">
<paper-icon-button class="volume style-scope ytmusic-player-bar" role="button" tabindex="0" aria-disabled="false" title="Mute" aria-label="Mute" aria-pressed="false"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z" class="style-scope iron-icon"></path></g></svg>
</iron-icon></paper-icon-button>
<paper-icon-button class="repeat style-scope ytmusic-player-bar" role="button" tabindex="0" aria-disabled="false" title="Repeat off" aria-label="Repeat off"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
<span class="repeat-button-a11y-label style-scope ytmusic-player-bar" aria-live="polite" aria-relevant="text">
Repeat off
</span>
<paper-icon-button class="shuffle style-scope ytmusic-player-bar" icon="yt-icons:shuffle" role="button" tabindex="0" aria-disabled="false" title="Shuffle" aria-label="Shuffle"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
<paper-icon-button class="expand-button style-scope ytmusic-player-bar" aria-haspopup="true" aria-owns="expanding-menu" icon="yt-icons:arrow-drop-down" role="button" tabindex="0" aria-disabled="false" title="More player controls" aria-label="More player controls"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M7 10l5 5 5-5z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
</div>
<ytmusic-player-expanding-menu id="expanding-menu" aria-expanded="false" no-cancel-on-outside-click="" restore-focus-on-close="true" class="style-scope ytmusic-player-bar" role="toolbar" aria-hidden="true" style="outline: none; display: none;">
<paper-slider id="expand-volume-slider" class="expand-volume-slider style-scope ytmusic-player-bar" slot="elements" max="100" min="0" step="5" role="slider" tabindex="0" aria-disabled="false" value="100" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" title="Volume" aria-label="Volume"><div id="sliderContainer" class="style-scope paper-slider"><div class="bar-container style-scope paper-slider"><paper-progress id="sliderBar" aria-hidden="true" class="style-scope paper-slider" role="progressbar" value="100" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" aria-disabled="false" style="touch-action: none;">
<div id="progressContainer" class="style-scope paper-progress">
<div id="secondaryProgress" class="style-scope paper-progress" hidden="" style="transform: scaleX(0);"></div>
<div id="primaryProgress" class="style-scope paper-progress" style="transform: scaleX(1);"></div>
</div>
</paper-progress></div><template is="dom-if" class="style-scope paper-slider"></template><div id="sliderKnob" class="slider-knob style-scope paper-slider" style="touch-action: none; left: 100%;"><div class="slider-knob-inner style-scope paper-slider" value="100"></div></div></div><template is="dom-if" class="style-scope paper-slider"></template></paper-slider><paper-icon-button id="expand-volume" class="expand-volume style-scope ytmusic-player-bar" slot="elements" role="button" tabindex="0" aria-disabled="false" title="Mute" aria-label="Mute" aria-pressed="false"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z" class="style-scope iron-icon"></path></g></svg>
</iron-icon></paper-icon-button><paper-icon-button id="expand-repeat" class="repeat style-scope ytmusic-player-bar" slot="elements" role="button" tabindex="0" aria-disabled="false" title="Repeat off" aria-label="Repeat off"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button><paper-icon-button id="expand-shuffle" slot="elements" icon="yt-icons:shuffle" class="style-scope ytmusic-player-bar" role="button" tabindex="0" aria-disabled="false" title="Shuffle" aria-label="Shuffle"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
</ytmusic-player-expanding-menu>
<paper-icon-button class="toggle-player-page-button style-scope ytmusic-player-bar" icon="yt-icons:arrow-drop-down" role="button" tabindex="0" aria-disabled="false" aria-label="Open player page"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M7 10l5 5 5-5z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon><paper-ripple id="ink" center="" class="circle style-scope paper-icon-button">
<div id="background" class="style-scope paper-ripple" style="opacity: 0;"></div>
<div id="waves" class="style-scope paper-ripple"></div>
</paper-ripple></paper-icon-button>
<paper-icon-button class="exit-fullscreen-button style-scope ytmusic-player-bar" icon="yt-icons:fullscreen_exit" role="button" tabindex="0" aria-disabled="false" title="Exit full screen" aria-label="Exit full screen"><iron-icon id="icon" class="style-scope paper-icon-button"><svg viewBox="0 0 24 24" preserveAspectRatio="xMidYMid meet" focusable="false" class="style-scope iron-icon" style="pointer-events: none; display: block; width: 100%; height: 100%;"><g class="style-scope iron-icon">
<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" class="style-scope iron-icon"></path>
</g></svg>
</iron-icon></paper-icon-button>
</div>
<span id="hover-time-info" class="style-scope ytmusic-player-bar" style="left: 0px; display: none;">0:00</span>
<paper-slider id="progress-bar" class="style-scope ytmusic-player-bar" role="slider" tabindex="0" aria-disabled="false" value="1" aria-valuemin="0" aria-valuemax="256" aria-valuenow="1" title="Seek slider" aria-label="Seek slider" aria-valuetext="0:01 of 4:16"><div id="sliderContainer" class="style-scope paper-slider"><div class="bar-container style-scope paper-slider"><paper-progress id="sliderBar" aria-hidden="true" class="style-scope paper-slider" role="progressbar" value="1" aria-valuenow="1" aria-valuemin="0" aria-valuemax="256" aria-disabled="false" style="touch-action: none;">
<div id="progressContainer" class="style-scope paper-progress">
<div id="secondaryProgress" class="style-scope paper-progress" style="transform: scaleX(0.476562);"></div>
<div id="primaryProgress" class="style-scope paper-progress" style="transform: scaleX(0.00390625);"></div>
</div>
</paper-progress></div><template is="dom-if" class="style-scope paper-slider"></template><div id="sliderKnob" class="slider-knob style-scope paper-slider" style="touch-action: none; left: 0.390625%;"><div class="slider-knob-inner style-scope paper-slider" value="1"></div></div></div><template is="dom-if" class="style-scope paper-slider"></template></paper-slider>
</ytmusic-player-bar>
I didn't get very far adapting this for music.youtube.com.
But for playlists, I did make a bookmarklet to view the selected playlist on the normal youtube domain.
javascript:void function(){var t="https://youtube.com"+window.location.pathname+window.location.search;window.location=t}();
Not sure if it can help, but https://github.com/MarshallOfSound/Google-Play-Music-Desktop-Player-UNOFFICIAL- has MPRIS support for YouTube Music, maybe the code could be used here.