Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2",
"background": {
"scripts": ["background.js"],
"persistent": false
"persistent": true
},
"content_scripts": [
{
Expand Down
165 changes: 85 additions & 80 deletions extension/providers/youtube-music.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,25 @@ class YoutubeMusic extends MprisBase {
}

getPosition(callback) {
console.log('YoutubeMusic', 'getPosition', arguments)

if (!$('ytmusic-player-bar .time-info').length)
return callback(0);

var text = $('ytmusic-player-bar .time-info').text();

text = text.split('/');

if (text.length != 2)
return 0;

callback(this.microSeconds(text[0].trim()));
const video = document.querySelector('video');
if (video) {
callback(Math.round(video.currentTime * 1e6));
} else {
callback(0);
}
}

setRate(callback) {
// Not supported
}

setVolume(callback) {

setVolume(callback, value) {
const video = document.querySelector('video');
if (video) {
video.volume = value;
}
callback()
this.update()
}

setShuffle(callback, value) {
Expand All @@ -49,128 +47,135 @@ class YoutubeMusic extends MprisBase {

next(callback) {
console.log('YoutubeMusic', 'next', arguments)

if ($('[aria-label="Next song"]').length)
$('[aria-label="Next song"]').click()
$('.next-button').click()

callback()
this.update()
}

previous(callback) {
console.log('YoutubeMusic', 'previous', arguments)

if ($('[aria-label="Previous song"]').length)
$('[aria-label="Previous song"]').click()
$('.previous-button').click()

callback()
this.update()
}

playPause(callback) {
console.log('YoutubeMusic', 'playPause', arguments)

if ($('[title="Pause"]').length)
$('[title="Pause"]').click()

if ($('[title="Play"]').length)
$('[title="Play"]').click()
const video = document.querySelector('video');
if (video) {
if (video.paused) video.play(); else video.pause();
}

callback()
this.update()
}

pause(callback) {
console.log('YoutubeMusic', 'pause', arguments)

if ($('[title="Pause"]').length)
$('[title="Pause"]').click()
const video = document.querySelector('video');
if (video) video.pause();

callback()
this.update()
}

play(callback) {
console.log('YoutubeMusic', 'play', arguments)

if ($('[title="Play"]').length)
$('[title="Play"]').click()
const video = document.querySelector('video');
if (video) video.play();

callback()
this.update()
}

update(callback) {
if ($('[title="Play"]').length) {
if ($('[title="Play"]').prop('disabled'))
this.media.PlaybackStatus = 'Stopped'
else
this.media.PlaybackStatus = 'Paused'
} else if ($('[title="Pause"]').length) {
this.media.PlaybackStatus = 'Playing'
seek(callback, offset) {
console.log('YoutubeMusic', 'seek', arguments)
const video = document.querySelector('video');
if (video) {
video.currentTime += offset / 1e6;
}
callback()
this.update()
}

if ($('[aria-label="Next song"]').length && ! $('[aria-label="Next song"]').prop('disabled'))
this.media.CanGoNext = true
else
this.media.CanGoNext = false

if ($('[aria-label="Previous song"]').length && ! $('[aria-label="Previous song"]').prop('disabled'))
this.media.CanGoPrevious = true
else
this.media.CanGoPrevious = false

if ($('ytmusic-player-bar .content-info-wrapper .title').length) {
this.media.Metadata["mpris:trackid"] = $('ytmusic-player-bar .content-info-wrapper .title').text()
this.media.Metadata["xesam:title"] = $('ytmusic-player-bar .content-info-wrapper .title').text()
setPosition(callback, trackId, position) {
console.log('YoutubeMusic', 'setPosition', arguments)
const video = document.querySelector('video');
if (video) {
video.currentTime = position / 1e6;
}
callback()
this.update()
}

update(callback) {
const video = document.querySelector('video');
if (!video) return;

if ($('ytmusic-player-bar .image').length)
this.media.Metadata["mpris:artUrl"] = $('ytmusic-player-bar .image').attr("src");
this.media.PlaybackStatus = video.paused ? 'Paused' : 'Playing';
this.media.Volume = video.volume;

const playerBar = $('ytmusic-player-bar');
if (!playerBar.length) return;

this.media.Metadata["xesam:url"] = location.href
const title = playerBar.find('.title').text().trim();
const subtitle = playerBar.find('.subtitle').text().trim();
const image = playerBar.find('.image').attr('src');

if (title) {
this.media.Metadata["mpris:trackid"] = title;
this.media.Metadata["xesam:title"] = title;
}

if (image) {
this.media.Metadata["mpris:artUrl"] = image;
}

if ($('ytmusic-player-bar .content-info-wrapper .subtitle').length && $('ytmusic-player-bar .content-info-wrapper .subtitle').text() && $('ytmusic-player-bar .content-info-wrapper .subtitle').text().split('•').length > 2) {
this.media.Metadata["xesam:album"] = $('ytmusic-player-bar .content-info-wrapper .subtitle').text().split('•')[1].trim()
this.media.Metadata["xesam:artist"] = [$('ytmusic-player-bar .content-info-wrapper .subtitle').text().split('•')[0].trim()]
this.media.Metadata["xesam:albumArtist"] = [$('ytmusic-player-bar .content-info-wrapper .subtitle').text().split('•')[0].trim()]
this.media.Metadata["xesam:url"] = window.location.href;

if (video.duration) {
this.media.Metadata["mpris:length"] = Math.round(video.duration * 1e6);
}

if ($('ytmusic-player-bar .time-info').length) {
var timestamp = $('ytmusic-player-bar .time-info').text().split('/');

if (timestamp.length == 2) {
this.media.Metadata["mpris:length"] = this.microSeconds(timestamp[1].trim())
}
if (subtitle) {
const parts = subtitle.split('•').map(p => p.trim());
if (parts.length >= 2) {
this.media.Metadata["xesam:artist"] = [parts[0].replace(/\n/g, ' ')];
this.media.Metadata["xesam:album"] = parts[1].replace(/\n/g, ' ');
this.media.Metadata["xesam:albumArtist"] = [parts[0].replace(/\n/g, ' ')];
}
}

this.media.CanGoNext = !playerBar.find('.next-button').prop('disabled');
this.media.CanGoPrevious = !playerBar.find('.previous-button').prop('disabled');

console.log('this.media', this.media);

if(! _.isEqual(this.oldMedia, this.media)){
if (!_.isEqual(this.oldMedia, this.media)) {
this.oldMedia = _.cloneDeep(this.media);
this.changed(this.media)
this.changed(this.media);
}
}

microSeconds(position) {
position = position.split(':');

if (position.length != 2)
return 0;

position = parseInt(position[0]) * 60 + parseInt(position[1])
position = position * 1e6
return position
const parts = position.split(':').reverse();
let seconds = 0;
if (parts.length >= 1) seconds += parseInt(parts[0]);
if (parts.length >= 2) seconds += parseInt(parts[1]) * 60;
if (parts.length >= 3) seconds += parseInt(parts[2]) * 3600;
return seconds * 1e6;
}
}

var youtubeMusic = new YoutubeMusic()
// Assign to window to prevent garbage collection as per user hint
window.youtubeMusic = new YoutubeMusic();

var checkExist = setInterval(function() {
if ($("ytmusic-player-bar").length) {
console.log('YoutubeMusic', 'checkExist', arguments)
clearInterval(checkExist);
youtubeMusic.init()
window.youtubeMusic.init()
}
}, 100);

2 changes: 1 addition & 1 deletion install.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def main(args):
if len(args) < 1:
args.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mpris2'))

ext_id = "ojjjidifjmbbckdjfiagdfdepbcmnicg"
ext_id = "mdgmciedjpifcefejkmhjlomlachicpl"
prog_path = args[0]

# Chrome's extension IDs are in hexadecimal but using a-p, referred
Expand Down
8 changes: 3 additions & 5 deletions mpris2
Original file line number Diff line number Diff line change
Expand Up @@ -448,11 +448,9 @@ def main():
conn = Gio.DBusConnection.new_for_address_sync(addr, connflags)
conn.set_exit_on_close(True)

name = "org.mpris.MediaPlayer2.chrome"
if players:
# if we are exposing more than one player we need to give them
# unique names
name += ".tab%d" % tabid
# Always include the tabId in the name to avoid a generic "chrome" instance
# which can conflict with the browser's built-in MPRIS.
name = "org.mpris.MediaPlayer2.chrome.tab%d" % tabid

player = TabPlayer(conn, name, tabid, msg["source"])
players[tabid] = player
Expand Down